Toggle navigation
Toggle navigation
This project
Loading...
Sign in
crp
/
crp-operation
Go to a project
Toggle navigation
Projects
Groups
Snippets
Help
Toggle navigation pinning
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Network
Create a new issue
Builds
Commits
Authored by
wanghongbo
2025-08-19 18:12:51 +0800
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
4ada4df556a286e76ef4bf2170624701ddc833f7
4ada4df5
1 parent
7bb3dab0
媒体分析
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
987 additions
and
16 deletions
pom.xml
src/main/java/com/wondertek/service/MediaInfoService.java
src/main/java/com/wondertek/service/impl/BackupMaterialServiceImpl.java
src/main/java/com/wondertek/service/impl/MediaInfoServiceImpl.java
src/main/java/com/wondertek/util/MediaAnalysisHelper.java
src/main/java/com/wondertek/util/MediaInfoUtil.java
src/main/java/com/wondertek/vo/media/AudioMedia.java
src/main/java/com/wondertek/vo/media/AudioSteam.java
src/main/java/com/wondertek/vo/media/ImageMedia.java
src/main/java/com/wondertek/vo/media/Media.java
src/main/java/com/wondertek/vo/media/MediaType.java
src/main/java/com/wondertek/vo/media/SteamMedia.java
src/main/java/com/wondertek/vo/media/Stream.java
src/main/java/com/wondertek/vo/media/VideoMedia.java
src/main/java/com/wondertek/vo/media/VideoStream.java
src/main/resources/application-dev.yml
pom.xml
View file @
4ada4df
...
...
@@ -46,7 +46,6 @@
<artifactId>
spring-boot-starter-json
</artifactId>
</dependency>
<dependency>
<groupId>
org.springframework.boot
</groupId>
<artifactId>
spring-boot-configuration-processor
</artifactId>
...
...
@@ -58,27 +57,18 @@
<artifactId>
lombok
</artifactId>
</dependency>
<dependency>
<groupId>
com.baomidou
</groupId>
<artifactId>
mybatis-plus-spring-boot3-starter
</artifactId>
<version>
3.5.7
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
fastjson
</artifactId>
<version>
1.2.47
</version>
</dependency>
<dependency>
<groupId>
com.alibaba
</groupId>
<artifactId>
druid
</artifactId>
...
...
@@ -122,16 +112,12 @@
<version>
23.0
</version>
</dependency>
<dependency>
<groupId>
ch.qos.logback
</groupId>
<artifactId>
logback-classic
</artifactId>
<!-- <version>1.2.3</version>-->
</dependency>
<dependency>
<groupId>
org.codehaus.janino
</groupId>
<artifactId>
janino
</artifactId>
...
...
@@ -143,6 +129,12 @@
<version>
5.8.32
</version>
</dependency>
<dependency>
<groupId>
commons-io
</groupId>
<artifactId>
commons-io
</artifactId>
<version>
2.15.1
</version>
</dependency>
</dependencies>
<build>
...
...
src/main/java/com/wondertek/service/MediaInfoService.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
service
;
import
com.wondertek.vo.media.Media
;
/**
* @description 媒体分析
* @author W5669
* @date 2025/8/19 17:27
*/
public
interface
MediaInfoService
{
/**
* 获取媒体信息
* @param mediaPath 媒体文件路径
* @param logId 日志id
* @return 返回null时说明处理有异常
*/
Media
getMediaInfo
(
String
mediaPath
,
String
logId
)
throws
Exception
;
}
...
...
src/main/java/com/wondertek/service/impl/BackupMaterialServiceImpl.java
View file @
4ada4df
package
com
.
wondertek
.
service
.
impl
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.core.convert.ConvertException
;
import
cn.hutool.core.util.ObjectUtil
;
import
cn.hutool.http.HttpRequest
;
import
cn.hutool.http.HttpResponse
;
import
cn.hutool.json.JSONUtil
;
import
com.alibaba.fastjson.JSON
;
import
com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
;
import
com.baomidou.mybatisplus.core.metadata.IPage
;
import
com.baomidou.mybatisplus.extension.plugins.pagination.Page
;
...
...
@@ -23,7 +26,10 @@ import com.wondertek.mapper.BackupMaterialMapper;
import
com.wondertek.mapper.StreamTaskMapper
;
import
com.wondertek.service.BackupMaterialService
;
import
com.wondertek.service.FileService
;
import
com.wondertek.service.MediaInfoService
;
import
com.wondertek.util.*
;
import
com.wondertek.vo.media.Media
;
import
com.wondertek.vo.media.MediaType
;
import
jakarta.annotation.Resource
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
...
...
@@ -59,6 +65,8 @@ public class BackupMaterialServiceImpl extends ServiceImpl<BackupMaterialMapper,
private
String
recGetImageUrl
;
@Value
(
"${file.previewUrl}"
)
private
String
previewUrl
;
@Resource
private
MediaInfoService
mediaInfoService
;
@Override
...
...
@@ -289,8 +297,6 @@ public class BackupMaterialServiceImpl extends ServiceImpl<BackupMaterialMapper,
}
catch
(
Exception
e
)
{
return
ResultBean
.
error
(
"上传文件异常"
);
}
//
//保存垫片素材表
BackupMaterial
backupMaterial
=
new
BackupMaterial
();
...
...
@@ -336,6 +342,23 @@ public class BackupMaterialServiceImpl extends ServiceImpl<BackupMaterialMapper,
log
.
error
(
"请求能力平台定帧抽图接口失败,url:{}"
,
switchStreamUrl
,
e
);
}
//媒体分析获取时长
try
{
Media
media
=
mediaInfoService
.
getMediaInfo
(
destFilePath
,
fileId
);
String
type
=
media
.
getType
();
Long
duration
=
0
l
;
//时长
switch
(
type
)
{
case
MediaType
.
VIDEO_TYPE
:
cn
.
hutool
.
json
.
JSONObject
jsonObject
=
JSONUtil
.
parseObj
(
media
);
duration
=
Double
.
valueOf
(
jsonObject
.
get
(
"duration"
,
Double
.
class
)
*
1000
).
longValue
();
backupMaterial
.
setDuration
(
duration
);
}
}
catch
(
NumberFormatException
|
ConvertException
e
)
{
log
.
error
(
"媒体分析获取时长报错:e={}"
,
e
);
}
catch
(
Exception
e
)
{
throw
new
RuntimeException
(
e
);
}
backupMaterialMapper
.
insert
(
backupMaterial
);
return
ResultBean
.
ok
(
"新增素材成功"
);
...
...
src/main/java/com/wondertek/service/impl/MediaInfoServiceImpl.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
service
.
impl
;
import
cn.hutool.core.collection.CollectionUtil
;
import
cn.hutool.json.JSONUtil
;
import
com.fasterxml.jackson.databind.JsonNode
;
import
com.fasterxml.jackson.databind.ObjectMapper
;
import
com.wondertek.service.MediaInfoService
;
import
com.wondertek.util.MediaAnalysisHelper
;
import
com.wondertek.util.MediaInfoUtil
;
import
com.wondertek.vo.media.*
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.lang3.StringUtils
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.stereotype.Service
;
import
org.springframework.util.CollectionUtils
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
import
java.util.Iterator
;
import
java.util.List
;
/**
* @description 媒体分析
* @author W5669
* @date 2025/8/19 17:57
* @param null
*/
@Service
@Slf4j
public
class
MediaInfoServiceImpl
implements
MediaInfoService
{
@Autowired
private
MediaInfoUtil
mediaInfoUtil
;
private
static
final
ObjectMapper
MAPPER
=
new
ObjectMapper
();
@Override
public
Media
getMediaInfo
(
String
mediaPath
,
String
logId
)
throws
Exception
{
log
.
info
(
"[Media Analysis] getMediaInfo mediaPath:{},logId:{}"
,
mediaPath
,
logId
);
long
startTime
=
System
.
currentTimeMillis
();
// 工具绝对路径
String
mediaInfoPath
=
mediaInfoUtil
.
mediaInfoPath
();
log
.
info
(
"[Media Analysis] mediaInfo tool path:{} "
,
mediaInfoPath
);
String
mediaInfoJson
;
try
{
mediaInfoJson
=
MediaAnalysisHelper
.
analysis
(
mediaInfoPath
,
mediaPath
,
logId
);
log
.
info
(
"[Media Analysis] getMediaInfo mediaInfoJson:{}"
,
mediaInfoJson
);
}
catch
(
Exception
e
)
{
log
.
error
(
"[Media Analysis] getMediaInfo Exception:{}"
,
e
);
throw
e
;
}
if
(
StringUtils
.
isBlank
(
mediaInfoJson
))
{
return
null
;
}
Media
media
;
// 解析工具返回JOSN数据
try
{
String
mediaType
=
getMediaType
(
mediaInfoJson
);
log
.
info
(
"[Media Analysis] getMediaInfo mediaType:{}"
,
mediaType
);
switch
(
mediaType
)
{
case
MediaType
.
IMAGE_TYPE
:
media
=
parseImageMedia
(
mediaInfoJson
);
break
;
case
MediaType
.
AUDIO_TYPE
:
media
=
parseAudioMedia
(
mediaInfoJson
);
break
;
case
MediaType
.
VIDEO_TYPE
:
media
=
parseVideoMedia
(
mediaInfoJson
);
break
;
default
:
throw
new
Exception
(
"MediaInfo Cannot analysis media format"
);
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[Media Analysis] getMediaInfo parse json error:{}"
,
e
);
throw
e
;
}
log
.
info
(
"[Media Analysis] getMediaInfo,mediaPath={}logId={},spendTime={}"
,
mediaPath
,
logId
,
System
.
currentTimeMillis
()
-
startTime
);
return
media
;
}
/**
* 判断媒体类型
*
* @param mediaInfoJson
* @return MediaType类定义字符串,无法解析返回空字符串
* @throws Exception
*/
private
String
getMediaType
(
String
mediaInfoJson
)
throws
Exception
{
JsonNode
root
=
MAPPER
.
readTree
(
mediaInfoJson
);
JsonNode
trackNode
=
root
.
get
(
"media"
).
get
(
"track"
);
Iterator
<
JsonNode
>
elements
=
trackNode
.
elements
();
List
<
String
>
typeList
=
new
ArrayList
<>();
while
(
elements
.
hasNext
())
{
JsonNode
node
=
elements
.
next
();
String
type
=
node
.
get
(
"@type"
).
asText
();
typeList
.
add
(
type
);
}
if
(!
CollectionUtils
.
isEmpty
(
typeList
))
{
if
(
typeList
.
contains
(
MediaType
.
VIDEO_TYPE
))
{
return
MediaType
.
VIDEO_TYPE
;
}
if
(
typeList
.
contains
(
MediaType
.
AUDIO_TYPE
))
{
return
MediaType
.
AUDIO_TYPE
;
}
if
(
typeList
.
contains
(
MediaType
.
IMAGE_TYPE
))
{
return
MediaType
.
IMAGE_TYPE
;
}
}
return
""
;
}
/**
* 图片JOSN数据的解析
*
* @param mediaInfoJson
* @return
*/
private
Media
parseImageMedia
(
String
mediaInfoJson
)
throws
Exception
{
log
.
info
(
"[Media Analysis] parseImageMedia"
);
ImageMedia
imageMedia
=
new
ImageMedia
();
JsonNode
root
=
MAPPER
.
readTree
(
mediaInfoJson
);
JsonNode
mediaNode
=
root
.
get
(
"media"
);
// Media Type
imageMedia
.
setType
(
MediaType
.
IMAGE_TYPE
);
// Media fileName
String
fileName
=
mediaNode
.
get
(
"@ref"
).
asText
();
imageMedia
.
setFileName
(
fileName
);
JsonNode
trackNode
=
mediaNode
.
get
(
"track"
);
Iterator
<
JsonNode
>
elemIterator
=
trackNode
.
elements
();
while
(
elemIterator
.
hasNext
())
{
JsonNode
node
=
elemIterator
.
next
();
String
elementType
=
node
.
path
(
"@type"
).
asText
();
if
(
elementType
.
equals
(
"General"
))
{
// Media fileExtension
String
fileExtension
=
paserUncertainNode
(
node
,
"FileExtension"
);
imageMedia
.
setFileExtension
(
fileExtension
);
// Media format
String
format
=
paserUncertainNode
(
node
,
"Format"
);
imageMedia
.
setFormat
(
format
);
// Media size
String
fileSize
=
paserUncertainNode
(
node
,
"FileSize"
);
imageMedia
.
setSize
(
fileSize
);
}
else
if
(
elementType
.
equals
(
MediaType
.
IMAGE_TYPE
))
{
// ImageMedia fileExtension
String
width
=
parseNumberValueNode
(
node
,
"Width"
);
imageMedia
.
setWidth
(
width
);
// ImageMedia Height
String
height
=
parseNumberValueNode
(
node
,
"Height"
);
imageMedia
.
setHeight
(
height
);
// ImageMedia colorSpace
String
colorSpace
=
paserUncertainNode
(
node
,
"ColorSpace"
);
imageMedia
.
setColorSpace
(
colorSpace
);
// ImageMedia chromaSubsampling
String
chromaSubsampling
=
paserUncertainNode
(
node
,
"ChromaSubsampling"
);
imageMedia
.
setChromaSubsampling
(
chromaSubsampling
);
// ImageMedia bitDepth
String
bitDepth
=
paserUncertainNode
(
node
,
"BitDepth"
);
imageMedia
.
setBitDepth
(
bitDepth
);
}
}
log
.
info
(
"[Media Analysis] parseImageMedia over:{}"
,
imageMedia
);
return
imageMedia
;
}
/**
* 音频JOSN数据的解析
*
* @param mediaInfoJson
* @return
*/
private
Media
parseAudioMedia
(
String
mediaInfoJson
)
throws
Exception
{
log
.
info
(
"[Media Analysis] parseAudioMedia"
);
AudioMedia
audioMedia
=
new
AudioMedia
();
JsonNode
root
=
MAPPER
.
readTree
(
mediaInfoJson
);
JsonNode
mediaNode
=
root
.
get
(
"media"
);
// Media Type
audioMedia
.
setType
(
MediaType
.
AUDIO_TYPE
);
// Media fileName
String
fileName
=
mediaNode
.
get
(
"@ref"
).
asText
();
audioMedia
.
setFileName
(
fileName
);
JsonNode
trackNode
=
mediaNode
.
get
(
"track"
);
Iterator
<
JsonNode
>
elemIterator
=
trackNode
.
elements
();
List
<
Stream
>
streamList
=
new
ArrayList
<>();
while
(
elemIterator
.
hasNext
())
{
JsonNode
node
=
elemIterator
.
next
();
String
elementType
=
node
.
path
(
"@type"
).
asText
();
if
(
elementType
.
equals
(
"General"
))
{
// Media fileExtension
String
fileExtension
=
paserUncertainNode
(
node
,
"FileExtension"
);
audioMedia
.
setFileExtension
(
fileExtension
);
// Media format
String
format
=
paserUncertainNode
(
node
,
"Format"
);
audioMedia
.
setFormat
(
format
);
// Media size
String
fileSize
=
paserUncertainNode
(
node
,
"FileSize"
);
audioMedia
.
setSize
(
fileSize
);
// StreamMedia audioCount
String
audioCount
=
paserUncertainNode
(
node
,
"AudioCount"
);
audioMedia
.
setAudioCount
(
audioCount
);
// StreamMedia duration
String
duration
=
parseNumberValueNode
(
node
,
"Duration"
);
audioMedia
.
setDuration
(
duration
);
// StreamMedia overallBitRate
String
overallBitRate
=
paserUncertainNode
(
node
,
"OverallBitRate"
);
audioMedia
.
setOverallBitRate
(
overallBitRate
);
// StreamMedia overallBitRateMode
String
overallBitRateMode
=
paserUncertainNode
(
node
,
"OverallBitRate_Mode"
);
audioMedia
.
setOverallBitRateMode
(
overallBitRateMode
);
}
else
if
(
elementType
.
equals
(
MediaType
.
AUDIO_TYPE
))
{
Stream
stream
=
parseStream
(
node
,
MediaType
.
AUDIO_TYPE
);
streamList
.
add
(
stream
);
}
}
audioMedia
.
setSteams
(
streamList
);
log
.
info
(
"[Media Analysis] parseAudioMedia over:{}"
,
audioMedia
);
return
audioMedia
;
}
/**
* 视频JOSN数据的解析
*
* @param mediaInfoJson
* @return
*/
private
Media
parseVideoMedia
(
String
mediaInfoJson
)
throws
Exception
{
log
.
info
(
"[Media Analysis] parseVideoMedia"
);
VideoMedia
videoMedia
=
new
VideoMedia
();
JsonNode
root
=
MAPPER
.
readTree
(
mediaInfoJson
);
JsonNode
mediaNode
=
root
.
get
(
"media"
);
videoMedia
.
setOriginalInfo
(
JSONUtil
.
parseObj
(
mediaInfoJson
).
toString
());
// Media Type
videoMedia
.
setType
(
MediaType
.
VIDEO_TYPE
);
// Media fileName
String
fileName
=
mediaNode
.
get
(
"@ref"
).
asText
();
videoMedia
.
setFileName
(
fileName
);
JsonNode
trackNode
=
mediaNode
.
get
(
"track"
);
Iterator
<
JsonNode
>
elemIterator
=
trackNode
.
elements
();
List
<
Stream
>
streamList
=
new
ArrayList
<>();
while
(
elemIterator
.
hasNext
())
{
JsonNode
node
=
elemIterator
.
next
();
String
elementType
=
node
.
path
(
"@type"
).
asText
();
if
(
elementType
.
equals
(
"General"
))
{
// Media fileExtension
String
fileExtension
=
paserUncertainNode
(
node
,
"FileExtension"
);
videoMedia
.
setFileExtension
(
fileExtension
);
// Media format
String
format
=
paserUncertainNode
(
node
,
"Format"
);
videoMedia
.
setFormat
(
format
);
// Media size
String
fileSize
=
paserUncertainNode
(
node
,
"FileSize"
);
videoMedia
.
setSize
(
fileSize
);
// StreamMedia audioCount
String
audioCount
=
paserUncertainNode
(
node
,
"AudioCount"
);
videoMedia
.
setAudioCount
(
audioCount
);
// StreamMedia duration
String
duration
=
parseNumberValueNode
(
node
,
"Duration"
);
videoMedia
.
setDuration
(
duration
);
// StreamMedia overallBitRate
String
overallBitRate
=
paserUncertainNode
(
node
,
"OverallBitRate"
);
videoMedia
.
setOverallBitRate
(
overallBitRate
);
// StreamMedia overallBitRateMode
String
overallBitRateMode
=
paserUncertainNode
(
node
,
"OverallBitRate_Mode"
);
videoMedia
.
setOverallBitRateMode
(
overallBitRateMode
);
// VideoMedia videoCount
String
videoCount
=
paserUncertainNode
(
node
,
"VideoCount"
);
videoMedia
.
setVideoCount
(
videoCount
);
// VideoMedia formatProfile
String
formatProfile
=
paserUncertainNode
(
node
,
"Format_Profile"
);
videoMedia
.
setFormatProfile
(
formatProfile
);
}
else
if
(
elementType
.
equals
(
MediaType
.
AUDIO_TYPE
))
{
Stream
stream
=
parseStream
(
node
,
MediaType
.
AUDIO_TYPE
);
streamList
.
add
(
stream
);
}
else
if
(
elementType
.
equals
(
MediaType
.
VIDEO_TYPE
))
{
Stream
stream
=
parseStream
(
node
,
MediaType
.
VIDEO_TYPE
);
streamList
.
add
(
stream
);
}
}
videoMedia
.
setSteams
(
streamList
);
log
.
info
(
"[Media Analysis] parseVideoMedia over:{}"
,
videoMedia
);
return
videoMedia
;
}
/**
* 处理一些不确定的节点
*
* @param parentNode
* 父节点
* @param name
* 子节点名称
* @return
*/
private
String
paserUncertainNode
(
JsonNode
parentNode
,
String
name
)
{
JsonNode
node
=
parentNode
.
get
(
name
);
if
(
node
!=
null
)
{
return
node
.
asText
();
}
return
""
;
}
/**
* 解析数值字段
*
* @param parentNode
* @param name
* @return
*/
private
String
parseNumberValueNode
(
JsonNode
parentNode
,
String
name
)
{
String
parseResult
=
null
;
try
{
parseResult
=
paserUncertainNode
(
parentNode
,
name
);
if
(
StringUtils
.
isNotBlank
(
parseResult
))
{
String
valueString
=
parseResult
;
// 处理MediaInfo异常返回,比如:分辨率返回"1920 / 1920"这种情形
if
(
parseResult
.
contains
(
"/"
))
{
List
<
String
>
splitResult
=
Arrays
.
asList
(
StringUtils
.
split
(
parseResult
,
"/"
));
if
(
CollectionUtil
.
isNotEmpty
(
splitResult
))
{
valueString
=
splitResult
.
get
(
0
).
trim
();
}
}
Double
valueDouble
=
Double
.
parseDouble
(
valueString
);
// 目的做个校验
log
.
info
(
"[Media Analysis] parseNumberValueNode check number value:{}"
,
valueDouble
);
return
valueString
;
}
}
catch
(
Exception
e
)
{
log
.
error
(
"[Media Analysis] parseNumberValueNode parser value:{} error:{}"
,
parseResult
,
e
);
return
"0"
;
}
return
"0"
;
}
/**
* 解析音视频流JSON数据
*
* @param parentNode
* 节点
* @param streamType
* 音频或者视频 MediaType取值
* @return
*/
private
Stream
parseStream
(
JsonNode
parentNode
,
String
streamType
)
{
Stream
stream
=
null
;
if
(
streamType
.
equals
(
MediaType
.
AUDIO_TYPE
))
{
stream
=
new
AudioSteam
();
}
else
if
(
streamType
.
equals
(
MediaType
.
VIDEO_TYPE
))
{
stream
=
new
VideoStream
();
}
if
(
stream
==
null
)
{
return
null
;
}
// 共同的属性
String
steamType
=
paserUncertainNode
(
parentNode
,
"@type"
);
stream
.
setStreamType
(
steamType
);
String
id
=
paserUncertainNode
(
parentNode
,
"ID"
);
stream
.
setId
(
id
);
String
streamOrder
=
paserUncertainNode
(
parentNode
,
"StreamOrder"
);
stream
.
setStreamOrder
(
streamOrder
);
String
format
=
paserUncertainNode
(
parentNode
,
"Format"
);
stream
.
setFormat
(
format
);
String
formatProfile
=
paserUncertainNode
(
parentNode
,
"Format_Profile"
);
stream
.
setFormatProfile
(
formatProfile
);
String
duration
=
parseNumberValueNode
(
parentNode
,
"Duration"
);
stream
.
setDuration
(
duration
);
String
bitRateMode
=
paserUncertainNode
(
parentNode
,
"BitRate_Mode"
);
stream
.
setBitRateMode
(
bitRateMode
);
String
bitRate
=
paserUncertainNode
(
parentNode
,
"BitRate"
);
stream
.
setBitRate
(
bitRate
);
String
bitRateMinimum
=
paserUncertainNode
(
parentNode
,
"BitRate_Minimum"
);
stream
.
setBitRateMinimum
(
bitRateMinimum
);
String
bitRateMaximum
=
paserUncertainNode
(
parentNode
,
"BitRate_Maximum"
);
stream
.
setBitRateMaximum
(
bitRateMaximum
);
String
frameRate
=
paserUncertainNode
(
parentNode
,
"FrameRate"
);
stream
.
setFrameRate
(
frameRate
);
String
frameCount
=
paserUncertainNode
(
parentNode
,
"FrameCount"
);
stream
.
setFrameCount
(
frameCount
);
String
bitDepth
=
paserUncertainNode
(
parentNode
,
"BitDepth"
);
stream
.
setBitDepth
(
bitDepth
);
String
streamSize
=
paserUncertainNode
(
parentNode
,
"StreamSize"
);
stream
.
setStreamSize
(
streamSize
);
// 处理音视频独特的属性
if
(
streamType
.
equals
(
MediaType
.
AUDIO_TYPE
))
{
AudioSteam
audioSteam
=
(
AudioSteam
)
stream
;
String
samplingRate
=
paserUncertainNode
(
parentNode
,
"SamplingRate"
);
audioSteam
.
setSamplingRate
(
samplingRate
);
String
samplingCount
=
paserUncertainNode
(
parentNode
,
"SamplingCount"
);
audioSteam
.
setSamplingCount
(
samplingCount
);
String
channels
=
paserUncertainNode
(
parentNode
,
"Channels"
);
audioSteam
.
setChannels
(
channels
);
}
else
if
(
streamType
.
equals
(
MediaType
.
VIDEO_TYPE
))
{
VideoStream
videoStream
=
(
VideoStream
)
stream
;
String
formatLevel
=
paserUncertainNode
(
parentNode
,
"Format_Level"
);
videoStream
.
setFormatLevel
(
formatLevel
);
String
formatSettingsGOP
=
paserUncertainNode
(
parentNode
,
"Format_Settings_GOP"
);
videoStream
.
setFormatSettingsGOP
(
formatSettingsGOP
);
String
frameRateMode
=
paserUncertainNode
(
parentNode
,
"FrameRate_Mode"
);
videoStream
.
setFrameRateMode
(
frameRateMode
);
String
width
=
parseNumberValueNode
(
parentNode
,
"Width"
);
videoStream
.
setWidth
(
width
);
String
height
=
parseNumberValueNode
(
parentNode
,
"Height"
);
videoStream
.
setHeight
(
height
);
String
displayAspectRatio
=
paserUncertainNode
(
parentNode
,
"DisplayAspectRatio"
);
videoStream
.
setDisplayAspectRatio
(
displayAspectRatio
);
String
colorSpace
=
paserUncertainNode
(
parentNode
,
"ColorSpace"
);
videoStream
.
setColorSpace
(
colorSpace
);
String
chromaSubsampling
=
paserUncertainNode
(
parentNode
,
"ChromaSubsampling"
);
videoStream
.
setChromaSubsampling
(
chromaSubsampling
);
String
scanType
=
paserUncertainNode
(
parentNode
,
"ScanType"
);
videoStream
.
setScanType
(
scanType
);
}
return
stream
;
}
}
...
...
src/main/java/com/wondertek/util/MediaAnalysisHelper.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
util
;
import
lombok.extern.slf4j.Slf4j
;
import
org.apache.commons.io.IOUtils
;
import
java.io.InputStream
;
import
java.nio.charset.StandardCharsets
;
import
java.util.ArrayList
;
import
java.util.List
;
/**
* @Auther: WANGJING
* @Description: 媒体分析工具类
* @Date: 2019/11/1 9:40
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Slf4j
public
class
MediaAnalysisHelper
{
/**
* @Description: 获取媒体分析JSON数据
* @Auther: WANGJING
* @Param mediaInfoPath mediaInfo工具路径
* @Param mediaFilePath 媒体文件路径
* @Param logId 日志id
* @Return: 返回分析结果JSON数据
* @Version:
* @TaskId: YJ-348
*/
public
static
String
analysis
(
String
mediaInfoPath
,
String
mediaFilePath
,
String
logId
)
throws
Exception
{
long
startTime
=
System
.
currentTimeMillis
();
log
.
info
(
"[Media Analysis] MediaAnalysisHelper mediaInfoPath:{}, mediaFilePath:{},logId:{}"
,
mediaInfoPath
,
mediaFilePath
,
logId
);
List
<
String
>
commend
=
new
ArrayList
<>();
commend
.
add
(
mediaInfoPath
);
commend
.
add
(
"--OUTPUT=JSON"
);
// json格式输出
commend
.
add
(
mediaFilePath
);
ProcessBuilder
builder
=
new
ProcessBuilder
();
builder
.
command
(
commend
);
Process
process
=
builder
.
start
();
int
result
=
process
.
waitFor
();
if
(
result
!=
0
)
{
log
.
info
(
"[Media Analysis] MediaAnalysisHelper Process Failure result={}"
,
result
);
throw
new
Exception
(
"MediaInfo工具处理异常"
);
}
log
.
info
(
"[Media Analysis] MediaAnalysisHelper,mediaFilePath={}logId={},spendTime={}"
,
mediaFilePath
,
logId
,
System
.
currentTimeMillis
()
-
startTime
);
InputStream
inputStream
=
process
.
getInputStream
();
String
josnMediaInfo
=
IOUtils
.
toString
(
inputStream
,
StandardCharsets
.
UTF_8
);
return
josnMediaInfo
;
}
}
...
...
src/main/java/com/wondertek/util/MediaInfoUtil.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
util
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Value
;
import
org.springframework.stereotype.Component
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Component
@Slf4j
public
class
MediaInfoUtil
{
@Value
(
"${file.mediainfoPath}"
)
private
String
mediaInfoPath
;
/**
* 获取MediaInfo工具的路径
*
* @return
*/
public
String
mediaInfoPath
()
{
log
.
info
(
"[Media Analysis] mediaInfo path:{}"
,
mediaInfoPath
);
return
mediaInfoPath
;
}
}
...
...
src/main/java/com/wondertek/vo/media/AudioMedia.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
import
lombok.Data
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
public
class
AudioMedia
extends
SteamMedia
{
}
...
...
src/main/java/com/wondertek/vo/media/AudioSteam.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
import
lombok.Data
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
public
class
AudioSteam
extends
Stream
{
/**
* 采样评率 单位是赫兹
*/
private
String
samplingRate
;
/**
* 采样个数
*/
private
String
samplingCount
;
/**
* 声道
*/
private
String
channels
;
}
...
...
src/main/java/com/wondertek/vo/media/ImageMedia.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
import
lombok.Data
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
public
class
ImageMedia
extends
Media
{
/**
* 图片宽度 (单位:像素)
*/
private
String
width
;
/**
* 图片高度(单位:像素)
*/
private
String
height
;
/**
* 色彩空间 RGB YUV
*/
private
String
colorSpace
;
/**
* 色度采用 4:2:0 4:4:4等
*/
private
String
chromaSubsampling
;
/**
* 位深
*/
private
String
bitDepth
;
}
...
...
src/main/java/com/wondertek/vo/media/Media.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
import
com.fasterxml.jackson.annotation.JsonInclude
;
import
lombok.Data
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
@JsonInclude
(
JsonInclude
.
Include
.
NON_NULL
)
public
class
Media
{
/**
* 媒体文件 /mnt1/video/test.mp4
*/
private
String
fileName
;
/**
* 文件后缀名(传入媒体文件后缀,不是分析结果)
*/
private
String
fileExtension
;
/**
* 媒体类型 MediaType取值之一
*/
private
String
type
;
// 媒体类型
/**
* 媒体文件封装格式 视频:MPEG-4(mp4,mov),MPEG-TS(ts,mts),MPEG-PS(mpg),AVI(avi),Windows
* Media(wmv),Matroska(mkv)等 音频:MPEG Audio(mp3),Wave(wav)
* 图片:JPEG(jpg,jpeg),PNG(png),GIF(gif)
*/
private
String
format
;
/**
* 文件大小(单位:字节)
*/
private
String
size
;
}
...
...
src/main/java/com/wondertek/vo/media/MediaType.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
/**
* @Auther: WANGJING
* @Description: 媒体类型
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
// 媒体类型
public
class
MediaType
{
public
static
final
String
IMAGE_TYPE
=
"Image"
;
// 图片
public
static
final
String
AUDIO_TYPE
=
"Audio"
;
// 音频
public
static
final
String
VIDEO_TYPE
=
"Video"
;
// 视频
}
...
...
src/main/java/com/wondertek/vo/media/SteamMedia.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
import
lombok.Data
;
import
java.util.List
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
public
class
SteamMedia
extends
Media
{
/**
* 音频流的个数
*/
private
String
audioCount
;
/**
* 时长(单位是:秒 274.176 精确到毫秒)
*/
private
String
duration
;
/**
* 平均混合码率(音视频)
*/
private
String
overallBitRate
;
/**
* 码率模式 VBR 变码率 ,CBR恒定码率
*/
private
String
overallBitRateMode
;
/**
* 音视频流
*/
private
List
<
Stream
>
steams
;
}
...
...
src/main/java/com/wondertek/vo/media/Stream.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
import
lombok.Data
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
public
class
Stream
{
/**
* 流的类型(Video,Audio)
*/
private
String
StreamType
;
/**
* 流的编号
*/
private
String
id
;
/**
* 流的顺序
*/
private
String
streamOrder
;
/**
* 流的编码格式 视频AVC,MPEG Video 音频AAC,MPEG Audio,PCM等
*/
private
String
format
;
/**
* 编码的Profile:视频:Baseline Extended Main,High 音频:"Layer 3"
*/
private
String
formatProfile
;
/**
* 时长 单位是秒:
*/
private
String
duration
;
/**
* 码率模式 VBR 变码率 ,CBR恒定码率
*/
private
String
bitRateMode
;
/**
* 码率 bps(VBR时是平均码率,CBR是恒定码率)
*/
private
String
bitRate
;
/**
* 码率最小值 bps
*/
private
String
bitRateMinimum
;
/**
* 码率最大值 bps
*/
private
String
bitRateMaximum
;
/**
* 帧率 fps
*/
private
String
frameRate
;
/**
* 帧数
*/
private
String
frameCount
;
/**
* 视频图位深或者声音采样精度
*/
private
String
bitDepth
;
/**
* 流大小 单位是字节
*/
private
String
streamSize
;
}
...
...
src/main/java/com/wondertek/vo/media/VideoMedia.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
import
lombok.Data
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
public
class
VideoMedia
extends
SteamMedia
{
/**
* 视频流的个数
*/
private
String
videoCount
;
/**
* 视频封装Profile
*/
private
String
formatProfile
;
/**
* media原始分析数据
*/
private
String
originalInfo
;
}
...
...
src/main/java/com/wondertek/vo/media/VideoStream.java
0 → 100644
View file @
4ada4df
package
com
.
wondertek
.
vo
.
media
;
import
lombok.Data
;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
public
class
VideoStream
extends
Stream
{
/**
* 编码的Level 3.1,
*/
private
String
formatLevel
;
/**
* 视频GOP值 例子"M=2, N=30"
*/
private
String
formatSettingsGOP
;
/**
* 帧模式 CFR 恒帧 VFR变帧
*/
private
String
frameRateMode
;
/**
* 视频宽度 单位像素
*/
private
String
width
;
/**
* 视频高度 单位像素
*/
private
String
height
;
/**
* 视频比例 1.778(16:9);1.33(4:3)
*/
private
String
displayAspectRatio
;
/**
* 色彩空间 RGB YUV
*/
private
String
colorSpace
;
/**
* 色度采用 4:2:0 4:4:4等
*/
private
String
chromaSubsampling
;
/**
* 视频扫描方式:Progressive 逐行扫描;Interlaced 隔行扫描
*/
private
String
scanType
;
}
...
...
src/main/resources/application-dev.yml
View file @
4ada4df
...
...
@@ -72,6 +72,7 @@ rec:
file
:
realPath
:
/home/wondertek/material_file_assets/dianpian/
previewUrl
:
https://dev.aivideo.cn/mdi/rehuo-wucai-file-service/preview/crp/
#预览前缀
mediainfoPath
:
/usr/bin/mediainfo
crp
:
pIp
:
180.167.180.242
...
...
Please
register
or
login
to post a comment