FFmpeg入门详解之82:FFmpeg转码器Java版之ava编码
创建数据库:db_webavtc
创建数据表:avcategory(素材类别)
id int primary key,
pid int ,
cname varchar(255),
cmemo varchar(1000)
CREATE TABLE `avcategory` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`pid` INT(11) NOT NULL,
`cname` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`cmemo` VARCHAR(1000) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
创建数据表:avtemplate(转码模板)
Id int primary key auto_increment,
tcTemplateId varchar(64),
tcTemplateName varchar(64),
tcFormatType int,//0:m3u8, 1:mp4, 2:flv
threadsNum int,//转码线程数
hlsSegmentTime int, //m3u8的切片长度(秒)
isMultiOutput int,
hasWaterMark int,
Priority int,
removeAV int,//去除视频(0),去除音频(1)
waterMark varchar(2048),//水印json串
tcTemplateDetails varchar(4096)//转码模板的json串
CREATE TABLE `avtemplate` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`tcTemplateId` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`tcTemplateName` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`tcTemplateEnglish` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`tcFormatType` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`isDeleted` INT(11) NULL DEFAULT '0',
`state` VARCHAR(64) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`threadsNum` INT(11) NULL DEFAULT '0',
`hlsSegmentTime` INT(11) NULL DEFAULT '10',
`tcFastMode` INT(11) NULL DEFAULT '0',
`isMultiOutput` INT(11) NULL DEFAULT '0',
`tcOutputFileCount` INT(11) NULL DEFAULT '0',
`hasWaterMark` INT(11) NULL DEFAULT '0',
`priority` INT(11) NULL DEFAULT '0',
`waterMark` VARCHAR(2048) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`tcTemplateDetails` VARCHAR(4096) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`createTime` DATETIME NULL DEFAULT NULL,
`removeAV` INT(11) NULL DEFAULT '0',
`isSystemReserved` INT(11) NULL DEFAULT '0',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_by_name` (`tcTemplateName`) USING BTREE,
INDEX `idx_by_tcid` (`tcTemplateId`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
ROW_FORMAT=COMPACT
AUTO_INCREMENT=43
;
创建数据表:avassets(素材)
Id int primary key auto_increment,
avAssetsGuid varchar(255),
avSrcName varchar(500),
avTitle varchar(255),
avMakeFullName varchar(500),
avType int,
avCategoryId int,
avState int,
avTag varchar(255),
avPoster varchar(255),
tcTemplateId varchar(64)
创建数据表:avtranscodetask(转码任务)
CREATE TABLE `avtranscodetask` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`tcTaskGuid` VARCHAR(128) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`avAssetsGuid` VARCHAR(128) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`tcTaskOutDir` VARCHAR(500) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`tcTaskOutName` VARCHAR(500) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`tcTaskState` INT(11) NULL DEFAULT NULL,
`tcTaskPercent` VARCHAR(128) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`tcConsumeTime` INT(11) NULL DEFAULT NULL,
`tcTranscoderIP` VARCHAR(128) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
PRIMARY KEY (`id`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
;
bean
创建AVCategory
创建AVTemplate
创建AVAssets
创建AVTranscodeTask
dao
AVCategoryDaoImpl
AVTemplateDaoImpl
AVAssetsDaoImpl
AVTrancodeTaskDaoImpl
service
AVCategoryService
AVCategoryServiceImpl
AVTemplateService
AVTemplateServiceImpl
AVAssetsService
AVAssetsServiceImpl
AVTrancodeTaskService
AVTrancodeTaskServiceImpl
action
AVCategoryAction
AVTemplateAction
稍微复杂,一点一点改造
AVAssetsAction
AVTrancodeTaskAction
UI
avcategoryList.jsp
avtemplateList.jsp
avassetsMother.jsp
文件上传的组件:webuploader.js
avassetsEdit.jsp:添加素材
avassetsEdit2.jsp: 编辑素材
avassetsAddNew.action
avassetsList.jsp:素材列表
avtranscodetaskList.jsp:转码列表
配置文件
Struts.xml: action
applicationContext.xml: *.hbm.xml, beans
创建数据表: ctype
CREATE TABLE `ctype` (
`ctid` INT(11) NOT NULL AUTO_INCREMENT,
`ctname` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`ctcode` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`ctno` INT(11) NULL DEFAULT NULL,
`ctdesc` VARCHAR(255) NULL DEFAULT NULL COLLATE 'utf8_general_ci',
`csCount` INT(11) NULL DEFAULT NULL,
`pid` INT(11) NULL DEFAULT NULL,
PRIMARY KEY (`ctid`) USING BTREE
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=14
;
db_webavtc
左侧导航树
ztree
Java调用ffmpeg进行转码
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
public class JavaFFmpeg extends Thread{
private boolean stoped = false;
public boolean isStoped() {
return stoped;
}
public void setStoped(boolean stoped) {
this.stoped = stoped;
}
public void run() {
// 在run方法中编写需要执行的操作
stoped = false;
openFFmpegExe();
stoped = true;
}
public static String readToString(String fileName) {
String encoding = "UTF-8";
File file = new File(fileName);
Long filelength = file.length();
byte[] filecontent = new byte[filelength.intValue()];
try {
FileInputStream in = new FileInputStream(file);
in.read(filecontent);
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
try {
return new String(filecontent, encoding);
} catch (UnsupportedEncodingException e) {
System.err.println("The OS does not support " + encoding);
e.printStackTrace();
return null;
}
}
public static void main(String[] args) {
System.out.println("hello,ffmpeg......");
// 在main方法(线程)中,创建线程对象,并启动线程.
JavaFFmpeg objTC = new JavaFFmpeg();
objTC.start();
String strFileContent;
while( !objTC.isStoped() ){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
strFileContent = readToString("d:/_movies/__test/ande_302.mp4.txt");
// frame=。
int nIdxFrameStart = strFileContent.lastIndexOf("frame=");
if(nIdxFrameStart >= 0){
int nIdxFrameEnd = strFileContent.indexOf((char)0x0A, nIdxFrameStart);
if(nIdxFrameEnd > 0){
String strFrames = strFileContent.substring(nIdxFrameStart, nIdxFrameEnd);
System.out.println(strFrames);// 打印输出信息
/// out_time=00:00:02.066576
int nIdxOutTimeStart = strFileContent.indexOf("out_time=", nIdxFrameEnd);
if(nIdxOutTimeStart > 0){
int nIdxOutTimeEnd = strFileContent.indexOf((char)0x0A, nIdxOutTimeStart);
if(nIdxOutTimeEnd > 0){
String strOutTime = strFileContent.substring(nIdxOutTimeStart, nIdxOutTimeEnd);
System.out.println(strOutTime);// 打印输出信息
}
}
}
}
}
System.out.println("bye,ffmpeg......");
}
//调用其他的可执行文件,例如:自己制作的exe,或是 下载 安装的软件.
private void openFFmpegExe() {
Runtime rn = Runtime.getRuntime();
Process p = null;
try {
///ffmpeg.exe -re -i d:/_movies/ande10.mp4 -vcodec libx264 -acodec aac -f flv rtmp://192.168.0.104/hls1/test
p = rn.exec("ffmpeg431.exe -progress d:/_movies/__test/ande_302.mp4.txt -i d:/_movies/__test/ande_302.mp4 -threads 1 -vcodec libx264 -acodec aac -y d:/_movies/__test/ande_302_test2.mp4" );
BufferedInputStream in = new BufferedInputStream(p.getErrorStream());
BufferedReader inBr = new BufferedReader(new InputStreamReader(in));
String lineStr;
System.out.println("开始转码");
while((lineStr = inBr.readLine())!=null){
//获得命令执行后在控制台的输出信息
//System.err.println("获得命令执行后在控制台的输出信息");
/System.out.println(lineStr);// 打印输出信息
}
// 检查命令是否执行失败。
if(p.waitFor()!=0){
if(p.exitValue()==1)//p.exitValue()==0表示正常结束,1:非正常结束
System.err.println("命令执行失败!");
}
inBr.close();in.close();
} catch (Exception e) {
System.out.println("Error exec:" + e.getMessage());
}
}
}
spring定时器
spring定时器一般有两种:
TimerTask、Quartz。
1.定时执行任务的类继承TimerTask:
Java代码
public class EmailReportTask extends TimerTask{
@Override
public void run() {
System.out.println(" EmailReportTask Run... ");
}
}
2.spring的配置文件:
Xml代码
<!-- Bean -->
<bean id="emailReportTask" class="com.fyl.spring.timertask.EmailReportTask" />
<!-- ScheduledTimerTask设置定时器属性 : period=定时器周期;delay=延迟多久启动
86400000代表24个小时;timerTask=执行定时任务的类对象 -->
<bean id="emailReportScheduleReportTask"
class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="timerTask" ref="emailReportTask" />
<property name="period" value="2000" />
<property name="delay" value="1000" />
</bean>
<!-- Spring的TimerFactoryBean负责启动定时任务;
scheduledTimerTasks = 需要启动的定时器任务的列表-->
<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="emailReportScheduleReportTask"/>
</list>
</property>
</bean>
<!-- ........................................ -->
<!-- ........................................ -->
<!-- ...................spring.timer..................... -->
<bean id="tcTimerTaskScheduler001" class="com.fyl.ssh.timer.TCTimerTaskScheduler">
</bean>
<bean id="scheduled_tcTimerTaskScheduler001" class="org.springframework.scheduling.timer.ScheduledTimerTask">
<property name="delay" value="1000" />
<property name="period" value="5000" />
<property name="timerTask" ref="tcTimerTaskScheduler001" />
</bean>
<bean class="org.springframework.scheduling.timer.TimerFactoryBean">
<property name="scheduledTimerTasks">
<list>
<ref bean="scheduled_tcTimerTaskScheduler001" />
</list>
</property>
</bean>
转码任务调度
查询“素材表”:等待状态
1.avassets:
avType: 0视频,1音频, 2图片
avState: <=100等待,101:转码中, 200:转码完成, 500:转码失败
2.avassets:素材绑定模板
3.avassets:查询对应模板的详细内容,根据tcTemplateGuid
AVAssetsAction
需要添加一个属性:AVTemplateService,需要在spring配置文件中配置
4.解析模板信息
(1)String------>Class
com.alibaba.fastjson.JSON
strAVTemplateString
Class obj = JSON.parseObject(strAVTemplateString, AVTemplateDetail.class);
(2)String--->JsonArray
JSONArray templateDetailJsonArray = new JSONArray();
templateDetailJsonArray =
JSONArray.parseArray(avtTmp.getTcTemplateDetails());
for(int i = 0; i < templateDetailJsonArray.size(); i++){
AVTemplateDetail avtDetail =
JSON.parseObject(templateDetailJsonArray.getString(i) , AVTemplateDetail.class);
System.out.println(":::"+ avtDetail.getvCodec() );
}
5.准备转码
(1)先在数据表中插入一条记录
定时器,每5秒钟,执行一次
avAssets: 检测 avState==101,转码中。
如果有,跳过本地timer;否则,继续开启新转码
(2)构造转码命令,开始转码,并更新转码进度
final public static String THE_TC_FFMPEG_CMDLINE_SINGLE =
"ffmpeg431 -i %s -vcodec %s -s %dx%d -acodec %s -f %s -y %s";
6.获取音视频素材的媒体基本信息
基本信息、视频信息、音频信息 ...
ffprobe431 -v quiet -print_format json -show_format
-show_streams D:\_movies\__test\ande_302_test2.mp4
ffprobe431 -i D:\_movies\__test\ande_302_test2.mp4
7.更新转码进度
(1)获取totalDuration
(2)获取实时转码进度,并转成百分比,更新数据库
(3)刷新转码列表页面
8.多码流输出
性能很高:只需要一次解码,同时进行多路编码
9.m3u8转码
切片命令行:
ffmpeg431.exe -i ande_302.mp4
-vbsf h264_mp4toannexb -vcodec libx264 -acodec aac
-strict -2 -s 640x480 -r 30 -g 150 -start_number 0 -hls_time 5 -hls_list_size
0 -threads 1 -f hls -y aaa.m3u8
-vbsf h264_mp4toannexb -vcodec libx264 -acodec aac
-strict -2 -s 960x540 -r 30 -g 150 -start_number 0 -hls_time 5 -hls_list_size
0 -threads 1 -f hls -y aaa.m3u8
-vbsf h264_mp4toannexb -vcodec libx264 -acodec aac
-strict -2 -s 1280x720 -r 30 -g 150 -start_number 0 -hls_time 5 -hls_list_size
0 -threads 1 -f hls -y aaa.m3u8
10.添加水印(图片、文字)
ffmpeg431.exe -i ande_302.mp4 -vf "drawtext=fontfile=simhei.ttf:text='hello, 您 好ffmpeg':x=(mod(2*n\,w+tw)-tw):y=10:fontcolor=#FF6600:fontsize=60" -f mp4 -y
ande_test_text3.mp4
11.水印:中文乱码
加上盘符后的表达式为
这个郁闷头疼:
原始语法:-vf drawtext="fontfile='d\:/_movies/__test/simhei.ttf':text=’xxx’"
Java语法:
String strXXX = “-vf drawtext=\"fontfile='d\\://_movies/__test/simhei.ttf’:text=’xxx’\"”;
Fontconfig error: Cannot load default config file
[Parsed_drawtext_0 @ 0102d840] Using "C:/WINDOWS/fonts/mingliub.ttc"
ffmpeg431 -i f:/fzavms1/fxhttp_out//__avsrc//2020/10/16/2020101614355828787ef9e22-0131-4777-b7a8-d063bc8d0b4b.mp4 -vf "drawtext=fontfile='d\:/_movies/__test/simhei.ttf':text='284378sxxxdqqq啊啊啊':x=(mod(2*n\,w+tw)-tw):y=10:fontcolor=#FF6600:fontsize=60" -vcodec libx264 -s 640x360 -acodec aac -threads 1 -f mp4 -y f:/fzavms1/fxhttp_out//__tasks//2020/10/16/2020101614355828787ef9e22-0131-4777-b7a8-d063bc8d0b4b.mp4/first.mp4
ffmpeg431 -i f:/fzavms1/fxhttp_out//__avsrc//2020/10/16/2020101614355828787ef9e22-0131-4777-b7a8-d063bc8d0b4b.mp4 -vf "drawtext=fontfile='d\:/_movies/__test/simhei.ttf':text='284378sxxxdqqq啊啊啊':x=(mod(2*n\,w+tw)-tw):y=10:fontcolor=#FF6600:fontsize=60" -vcodec libx264 -s 640x360 -acodec aac -threads 1 -f mp4 -y f:/fzavms1/fxhttp_out//__tasks//2020/10/16/2020101614355828787ef9e22-0131-4777-b7a8-d063bc8d0b4b.mp4/first.mp4
fastjson
String strWMJsonStr = JSON.toJSONString(objWaterMark, true);
WaterMark avtWaterMarkDetail = JSON.parseObject(strxxx , WaterMark.class);
大家好,我的第一本书正式出版了,可以在京东各大店铺抢购哦。
《FFmpeg入门详解--音视频原理及应用:梅会东:清华大学出版社》
京东自营链接:https://item.jd.com/13377793.html
京东其它链接:https://search.jd.com/Search?keyword=FFmpeg%E5%85%A5%E9%97%A8%E8%AF%A6%E8%A7%A3--%E9%9F%B3%E8%A7%86%E9%A2%91%E5%8E%9F%E7%90%86%E5%8F%8A%E5%BA%94%E7%94%A8&enc=utf-8&suggest=1.his.0.0&wq=&pvid=24e80535073b4e1f98e30a3e6963fe81
出书过程非常艰辛,来回校正了好几遍,后续还有FFmpeg系列的其它图书。
第一本:FFmpeg入门详解--音视频原理及应用--梅会东--清华大学出版社
第二本:FFmpeg入门详解--流媒体直播原理及应用--梅会东--清华大学出版社
第三本:FFmpeg入门详解--命令行及音视频特效原理及应用--梅会东--清华大学出版社
第四本:FFmpeg入门详解--SDK二次开发及直播美颜原理及应用--梅会东--清华大学出版社
===================================
FFmpeg入门详解之82:FFmpeg转码器Java版之ava编码相关推荐
- FFmpeg入门详解之6:VLC播放器简介
VLC播放器 VLC支持多种常见音视频格式,支持多种流媒体传输协议,也可当做本地流媒体服务器使用,功能十分强大. 官网下载地址:https://www.videolan.org/ VLC ...
- FFmpeg入门详解之116:rtsp live555摄像头直播
rtsp+live555摄像头直播 Live555直播流程简介与演示 第一步,读取摄像头数据 第二步,x264编码 第三步,扩展live555 第四步,vlc或ffplay播放 ffplay -sta ...
- FFmpeg入门详解之83:流媒体与直播技术
流媒体 流媒体又叫流式媒体,它是指商家用一个视频传送服务器(比如:vlc)把节目(比如:ande10.mp4)当成数据包发出,传送到网络上.用户通过解压设备对这些数据进行解压后,节目就会像发送前那样显 ...
- FFmpeg入门详解之117:视频监控的架构和流程
几张架构图带您快速了解视频监控 图一 图二 图三 图四 视频监控系统的简介 视频监控 视频监控是安全防范系统的重要组成部分,英文Cameras and Surveillance.传统的监控系统包括前端 ...
- FFmpeg入门详解之121:颜色空间转换RGB和YUV的原理与实战
5.颜色空间转换RGB和YUV的原理与实战 三种颜色空间模型:RGB.YUV.HSV 一.概述 颜色通常用三个独立的属性来描述,三个独立变量综合作用,自然就构成一个空间坐标,这就是颜色空间. 但被描述 ...
- FFmpeg入门详解之122:Qt5 FFmpeg本地摄像头采集预览实战
6.Qt5+FFmpeg本地摄像头采集预览实战 源码工程:S26_Test2 FFmpeg命令行处理摄像头 ffmpeg -list_devices true -f dshow -i dummy 命令 ...
- FFmpeg入门详解之124:Qt5 FFmpeg单路网络摄像头采集预览
Qt5+FFmpeg单路网络摄像头采集预览 源码工程:S26_Test4 RTSP协议简介 RTSP(Real Time Streaming Protocol),RFC2326 RTSP(Real T ...
- FFmpeg入门详解之111:RTSP协议2
rtsp消息详解 1.RTSP的消息有两大类,一是请求消息(request),一是回应消息(response),两种消息的格式不同. 请求消息格式: 方法 URI RTSP版本 CR LF 消息头 C ...
- FFmpeg入门详解之119:FFmpeg的SDK编程回顾总结并操练
3.FFmpeg的SDK编程回顾总结并操练 参考课程:"FFmpeg4.3--系列5--SDK二次开发详解与实战" FFmpeg主要框架 FFmpeg骨架:"八大金刚&q ...
最新文章
- 图解Transformer:Attention Is All You Need
- UrlDecode和base64
- 智慧办公的AI博弈——看飞企互联如何接招!
- Linux系统Logrotate服务介绍
- 火影忍者服务器维护时间,火影手游12月12日更新:仙鸣增加破霸体,小自来也变蛙时间减半!...
- Pandas系列(十五)stack和pivot实现数据透视
- [渝粤教育] 江苏农牧科技职业学院 兽医文化 参考 资料
- 三星手机如何分屏_艺术大片如何拍?快拜三星Galaxy S20 5G系列为师|三星|摄像头|手机|远景...
- 百战学堂python教学文档_尚学堂百战程序员:python对文件的操作
- STAP旁瓣干扰抑制与干扰对抗仿真
- 添加WhatsApp链接教程
- 石墨烯在生物医学上应用的研究进展_石墨烯在润滑油中的应用
- DELL服务器运行硬件检测
- 拿什么产品引流年轻女性?发什么能吸引女粉丝?
- B2C模式电商案例分享
- winusb —— 不再为你的usb设备编写驱动
- 后台管理系统中的登录页面
- iPad 使用技巧:备忘录
- shell win10 改成cmd_Win10 的 PowerShell、CMD 和 Windows Terminal 全方位美化配置方法
- HDU 6305 RMQ Similar Sequence(笛卡尔树)