视频处理
1.1 需求分析
原始视频通常需要经过编码处理,生成m3u8和ts文件方可基于HLS协议播放视频。通常用户上传原始视频,系统
自动处理成标准格式,系统对用户上传的视频自动编码、转换,最终生成m3u8文件和ts文件,处理流程如下:
1、用户上传视频成功
2、系统对上传成功的视频自动开始编码处理
3、用户查看视频处理结果,没有处理成功的视频用户可在管理界面再次触发处理
4、视频处理完成将视频地址及处理结果保存到数据库
视频处理开发
RabbitMQ 配置如下:
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.amqp.SimpleRabbitListenerContainerFactoryConfigurer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author Administrator
* @version 1.0
* @create 2018-07-12 9:04
**/
@Configuration
public class RabbitMQConfig {
public static final String EX_MEDIA_PROCESSTASK = "ex_media_processor";
//视频处理队列
@Value("${xc-service-manage-media.mq.queue-media-video-processor}")
public String queue_media_video_processtask;
//视频处理路由
@Value("${xc-service-manage-media.mq.routingkey-media-video}")
public String routingkey_media_video;
//消费者并发数量
public static final int DEFAULT_CONCURRENT = 10;
//消费消息的并发处理操作,需导入包:import org.springframework.amqp.rabbit.connection.ConnectionFactory;
@Bean("customContainerFactory")
public SimpleRabbitListenerContainerFactory containerFactory(SimpleRabbitListenerContainerFactoryConfigurer configurer, ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConcurrentConsumers(DEFAULT_CONCURRENT);
factory.setMaxConcurrentConsumers(DEFAULT_CONCURRENT);
configurer.configure(factory, connectionFactory);
return factory;
}
/**
* 交换机配置
* @return the exchange
*/
@Bean(EX_MEDIA_PROCESSTASK)
public Exchange EX_MEDIA_VIDEOTASK() {
return ExchangeBuilder.directExchange(EX_MEDIA_PROCESSTASK).durable(true).build();
}
//声明队列,该队列持久化,重启后还在,连接不独占,不用时,自动删除池中队列
@Bean("queue_media_video_processtask")
public Queue QUEUE_PROCESSTASK() {
Queue queue = new Queue(queue_media_video_processtask,true,false,true);
return queue;
}
/**
* 绑定队列到交换机 .
* @param queue the queue
* @param exchange the exchange
* @return the binding
*/
@Bean
public Binding binding_queue_media_processtask(@Qualifier("queue_media_video_processtask") Queue queue, @Qualifier(EX_MEDIA_PROCESSTASK) Exchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with(routingkey_media_video).noargs();
}
}
在application.yml中配置队列名称及routingkey
xc-service-manage-media:
mq:
#消息队列
queue-media-video-processor: queue_media_video_processor
#路由key
routingkey-media-video: routingkey_media_video
#视频路径前缀
video-location: D:/a1/xuechengzaixianUI/develop/video/
#视频转码软件路径
ffmpeg-path: D:/biancheng/ffmpeg-win64-static/bin/ffmpeg.exe
Process Builder类执行三方应用命令
1.2.2 视频处理技术方案
如何通过程序进行视频处理?
ffmpeg是一个可行的视频处理程序,可以通过Java调用ffmpeg.exe完成视频处理。
在java中可以使用Runtime类和Process Builder类两种方式来执行外部程序,工作中至少掌握一种。
本项目使用Process Builder的方式来调用ffmpeg完成视频处理。
关于Process Builder的测试如下:
import com.xuecheng.framework.utils.Mp4VideoUtil;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
/**
* @author Administrator
* @version 1.0
* @create 2018-07-12 9:11
**/
@SpringBootTest
@RunWith(SpringRunner.class)
public class TestProcessBuilder {
/**
*
* JAVA用ProcessBuilder对象,执行第三方命令。比如cmd相关命令
*/
@Test
public void testProcessBuilder() throws IOException {
//创建ProcessBuilder对象
ProcessBuilder processBuilder =new ProcessBuilder();
//设置执行的第三方程序(命令)
// processBuilder.command("ping","127.0.0.1","-t");
//查本机ip信息的命令
processBuilder.command("ipconfig");
// processBuilder.command("java","-jar","f:/xc-service-manage-course.jar");
//将标准输入流和错误输入流合并,通过标准输入流读取信息就可以拿到第三方程序输出的错误信息、正常信息
processBuilder.redirectErrorStream(true);
//启动一个进程
Process process = processBuilder.start();
//由于前边将错误和正常信息合并在输入流,只读取输入流
InputStream inputStream = process.getInputStream();
//将字节流转成字符流
InputStreamReader reader = new InputStreamReader(inputStream,"gbk");
//字符缓冲区
char[] chars = new char[1024];
int len = -1;
while((len = reader.read(chars))!=-1){
String string = new String(chars,0,</