任务需求:
对一批视频进行处理,去除其中的固定长度的片头和片尾。
基本情况:
- FFmpeg提供了一些基本的核心工具,包括剪切视频片段以及获取视频信息;
- FFmpeg没有提供针对需求的工具,尤其是固定片尾的处理;
- 需要综合FFmpeg的基本工具和shell脚本的文本处理工具,将视频长度提取出来进行处理,进而满足需求;
- 我之前都是在bat中使用FFmpeg简单进行视频批处理,但不是很了解Bat脚本及其处理文本的方法。论坛里有一些类似的文章只需4步实现批量删除音视频的片头片尾,不过没太仔细看,感兴趣的朋友可以了解一下;
- 不过我对shell脚本的文本处理很感兴趣。由于只是“半桶水”,所以还是要先感谢benarchen提供的利用shell脚本解决批量处理的方式;
- benarchen建议在安装Linux系统的设备中运行shell脚本,而我目前的设备安装的是Windows7,不能直接在命令行中运行;
- 不过我觉得应该可以在Windows7中使用Cygwin,运行该shell/bash脚本,曲线救国。
技能需求:
- Windows7中的命令行使用FFmpeg处理视频;
- Windows7中Cygwin的基本使用,在Cygwin中编辑、运行shell/bash 脚本;
- Shell脚本的一些基础知识,循环结构等等。
以上这些技能,如果都会的话,估计不需要继续看下去就已经知道该怎么操作了。不会或者像我一样时间久了不熟悉的话,需要先自学或者温习一下,否则会影响操作流程,我这里就不介绍了。
操作流程概括:
-. 先简单测试了一下在Cygwin中运行FFmpeg的情况,准备好待测试视频文件,在Cygwin命令行中分别输入:
nohup /cygdrive/e/Interest-0/010PC/000Tools/ffmpeg/bin/ffmpeg -i input > tmp.log
/cygdrive/e/Interest-0/010PC/000Tools/ffmpeg/bin/ffmpeg –i input.mp4 output.mp4
关于路径的问题,下面有描述。上面的命令运行正常,输出的log里面也包含了视频的Metadata、Duration等信息,表示可以在Cygwin中处理视频。
-. 最后,开始调试博主提供的shell脚本,有几处简单报错和需要修改的地方。当时改得很快,没来得及截图,简单描述一下:
- 原代码中的“for i in (.mp4,.mp3,*.avi ); do”,这一句循环结构有语法报错,我直接改成了“for i in *.mp4”;
- 原代码中的FFmpeg路径为“/usr/local/ffmpeg/bin/ffmpeg”,我是在Cygwin环境中的,所以要注意FFmpeg的路径:“/cygdrive/e/Interest-0/010PC/000Tools/ffmpeg/bin/ffmpeg”,其中的“/cygdrive/e”就是指E盘,要根据实际存放位置确定;
- 原代码中”/usr/local/ffmpeg/bin/ffmpeg -ss 00:00:07 -i $i -t n e w t i m e − c : v c o p y − c : a c o p y / d a t a / t m p / newtime -c:v copy -c:a copy /data/tmp/newtime−c:vcopy−c:acopy/data/tmp/i –y”,我对这一行的改动有两点,一是应根据个人需要使用视频的编码方式,二是我的一些待处理文件的文件名有空格,所以其中的“$i”,需要套上双引号,以适应这类较复杂的文件名。
运行通过的shell脚本:
#!/bin/bash
#我这里要切除的开头和结尾都是 31 秒
beg=31
end=31
#用 for 循环直接获取当前目录下的 mp4 文件循环处理,单个文件可以去掉 for 循环
for i in *.mp4
do
#将元数据信息临时保存到 tmp.log 文件中
nohup /cygdrive/e/Interest-0/010PC/000Tools/ffmpeg/bin/ffmpeg -i "$i" > tmp.log
#获取视频的时长,格式为 00:00:10,10 (时:分:秒,微妙)
time="`cat ./tmp.log |grep Duration: |awk '{print $2}'|awk -F "," '{print $1}'|xargs`"
echo $time
#求视频的总时长,先分别求出小时、分、秒的值,这里不处理微秒,可以忽略
hour="`echo $time |awk -F ":" '{print $1}' `"
min="`echo $time |awk -F ":" '{print $2}' `"
sec="`echo $time |awk -F ":" '{print $3}'|awk -F "." '{print $1}' `"
#echo $hour $min $sec
num1=`expr $hour \* 3600`
num2=`expr $min \* 60`
num3=$sec
#计算出视频的总时长(秒)
sum=`expr $num1 + $num2 + $num3`
#总时长减去开头和结尾就是截取后的视频时长,并且这里不需要再转回 hour:min:sec >的格式,直接使用结果即可
newtime=`expr $sum - $beg - $end`
echo $newtime
/cygdrive/e/Interest-0/010PC/000Tools/ffmpeg/bin/ffmpeg -i "$i" -ss 00:00:31 -t $newtime -c:v libx264 -c:a aac ./tmp/"$i"
done
小结
一套操作下来花了几十分钟,主要是因为有小半年没有接触Cygwin和bash,打开Cygwin的一瞬间茫茫然。一些基本的操作和命令一时间回想不起来,比如根目录的表示方式、Cygwin中关于驱动盘的路径表达式、shell脚本表达式编辑等等。查找了一下过去的笔记和资料,时间主要花在这上面和调试了。相信如果熟练的话,几分钟就可以了。
万幸,原代码中间的文本处理过程是完全OK的,节省了很多时间,再次感谢原作者benarchen的分享。
版权声明:本文为cheng_v原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。