wanghongbo

媒体分析

... ... @@ -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>
... ...
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;
}
... ...
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 = 0l;//时长
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("新增素材成功");
... ...
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;
}
}
... ...
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;
}
}
... ...
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;
}
}
... ...
package com.wondertek.vo.media;
import lombok.Data;
/**
* @Auther: WANGJING
* @Description:
* @Modifier:
* @Version:
* @TaskId: YJ-348
*/
@Data
public class AudioMedia extends SteamMedia {
}
... ...
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;
}
... ...
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;
}
... ...
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;
}
... ...
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"; // 视频
}
... ...
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;
}
... ...
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;
}
... ...
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;
}
... ...
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;
}
... ...
... ... @@ -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
... ...