1.2.3 视频处理实现
1.2.3.1确定消息格式
MQ消息统一采用json格式,视频处理生产方会向MQ发送如下消息,视频处理消费方接收此消息后进行视频处
理:
{“mediaId”:XXX}
1.2.3.2处理流程
1)接收视频处理消息
2)判断媒体文件是否需要处理(本视频处理程序目前只接收avi视频的处理)
当前只有avi文件需要处理,其它文件需要更新处理状态为“无需处理”。
3)处理前初始化处理状态为“未处理”
4)处理失败需要在数据库记录处理日志,及处理状态为“处理失败”
5)处理成功记录处理状态为“处理成功”
1.2.3.3数据模型
在MediaFile类中添加mediaFileProcess_m3u8属性记录ts文件列表,代码如下:
//处理状态
private String processStatus;
//hls处理
private MediaFileProcess_m3u8 mediaFileProcess_m3u8;
@Data
@ToString
public class MediaFileProcess_m3u8 extends MediaFileProcess {
//ts列表
private List<String> tslist;
}
3、处理任务类
在mq包下创建MediaProcessTask类,此类负责监听视频处理队列,并进行视频处理。
整个视频处理内容较多,这里分两部分实现:生成Mp4和生成m3u8,下边代码实现了生成mp4。
@Component
public class MediaProcessTask {
@Value("${xc-service-manage-media.ffmpeg-path}")
String ffmpeg_path;
//上传文件根目录
@Value("${xc-service-manage-media.video-location}")
String serverPath;
@Autowired
MediaFileRepository mediaFileRepository;
//接收视频处理消息进行视频处理
@RabbitListener(queues="${xc-service-manage-media.mq.queue-media-video-processor}",containerFactory = "customContainerFactory")
public void receiveMediaProcessTask(String msg){
//1、解析消息内容,得到mediaId
Map map = JSON.parseObject(msg, Map.class);
String mediaId = (String) map.get("mediaId");
//2、拿mediaId从数据库查询文件信息
Optional<MediaFile> optional = mediaFileRepository.findById(mediaId);
if(!optional.isPresent()){
return ;
}
MediaFile mediaFile = optional.get();
//文件类型
String fileType = mediaFile.getFileType();
if(!fileType.equals("avi")){
mediaFile.setProcessStatus("303004");//无需处理
mediaFileRepository.save(mediaFile);
return ;
}else{
//需要处理
mediaFile.setProcessStatus("303001");//处理中
mediaFileRepository.save(mediaFile);
}
//3、使用工具类将avi文件生成mp4
//String ffmpeg_path, String video_path, String mp4_name, String mp4folder_path
//要处理的视频文件的路径
String video_path = serverPath + mediaFile.getFilePath() + mediaFile.getFileName();
//生成的mp4的文件名称
String mp4_name = mediaFile.getFileId() + ".mp4";
//生成的mp4所在的路径
String mp4folder_path = serverPath + mediaFile.getFilePath();
//创建工具类对象
Mp4VideoUtil mp4VideoUtil =new Mp4VideoUtil(ffmpeg_path,video_path,mp4_name,mp4folder_path);
//进行处理
String result = mp4VideoUtil.generateMp4();
if(result == null || !result.equals("success")){
//处理失败
mediaFile.setProcessStatus("303003");
//定义mediaFileProcess_m3u8
MediaFileProcess_m3u8 mediaFileProcess_m3u8 = new MediaFileProcess_m3u8();
//记录失败原因
mediaFileProcess_m3u8.setErrormsg(result);
mediaFile.setMediaFileProcess_m3u8(mediaFileProcess_m3u8);
mediaFileRepository.save(mediaFile);
return ;
}
//4、将mp4生成m3u8和ts文件
//String ffmpeg_path, String video_path, String m3u8_name,String m3u8folder_path
//mp4视频文件路径
String mp4_video_path = serverPath + mediaFile.getFilePath() + mp4_name;
//m3u8_name文件名称
String m3u8_name = mediaFile.getFileId() +".m3u8";
//m3u8文件所在目录
String m3u8folder_path = serverPath + mediaFile.getFilePath() + "hls/";
HlsVideoUtil hlsVideoUtil = new HlsVideoUtil(ffmpeg_path,mp4_video_path,m3u8_name,m3u8folder_path);
//生成m3u8和ts文件
String tsResult = hlsVideoUtil.generateM3u8();
if(tsResult == null || !tsResult.equals("success")){
//处理失败
mediaFile.setProcessStatus("303003");
//定义mediaFileProcess_m3u8
MediaFileProcess_m3u8 mediaFileProcess_m3u8 = new MediaFileProcess_m3u8();
//记录失败原因
mediaFileProcess_m3u8.setErrormsg(result);
mediaFile.setMediaFileProcess_m3u8(mediaFileProcess_m3u8);
mediaFileRepository.save(mediaFile);
return ;
}
//处理成功
//获取ts文件列表
List<String> ts_list = hlsVideoUtil.get_ts_list();
mediaFile.setProcessStatus("303002");
//定义mediaFileProcess_m3u8
MediaFileProcess_m3u8 mediaFileProcess_m3u8 = new MediaFileProcess_m3u8();
mediaFileProcess_m3u8.setTslist(ts_list);
mediaFile.setMediaFileProcess_m3u8(mediaFileProcess_m3u8);
//保存fileUrl(此url就是视频播放的相对路径)
String fileUrl =mediaFile.getFilePath() + "hls/"+m3u8_name;
mediaFile.setFileUrl(fileUrl);
mediaFileRepository.save(mediaFile);
}
}
总结
前端将这个avi文件,进行分片上传
上传到下边文件夹
然后上传成功,Java的异步任务处理avi文件转为mp4,将mp4生成m3u8和ts文件
说明:
1、原始视频转成mp4如何判断转换成功?
根据视频时长来判断,取原视频和转换成功视频的时长(时分秒),如果相等则相同。
说明:
mp4转成m3u8如何判断转换成功?
第一、根据视频时长来判断,同mp4转换成功的判断方法。
第二、最后还要判断m3u8文件内容是否完整。
当视频上传成功后向MQ 发送视频 处理消息。
修改媒资管理服务的文件上传代码,当文件上传成功向MQ发送视频处理消息。