FFmpeg视频解码简单使用

这周主要在解决视频转码的问题,其实原本也没有什么问题,只是因为出现了部分开机视频文件在部分机器上卡死不能正常播放的问题,导致了外面一大批机器死机。对于一个做互联网电视的公司来说,电视死机那是致命的。所以最近才要严格限制视频格式以及进行主动转码测试验证,确保完全没问题的视频文件,才能进行投放。

ffmpeg是一款免费的,高效的视频转码工具,网上关于ffmpeg的使用有很多的介绍,这里我就不提了(主要是我也不知道。。。(@ο@)~ 😁),可以参考 雷神 的技术博客。天妒英才,希望天堂没有代码,雷神走好。

这次的转码工具是Linux系统下的sh脚本,主要有两个部分

1、基本配置

基本配置主要根据项目的实际需求配置相应的参数,比如帧率,比特率,分辨率,时长,采样率,声道。。。具体数据就不对外公布了。

2、执行命令

echo "--------------------------------------"
echo "intput file         : "${infile}
echo "output file         : "${outfile}
echo "output file format  : "${outFormat}
echo "duration limit      : "${durationLimit}
echo "video mode          : "${videoMode}
echo "video codec         : "${videoCodec}
echo "video profile       : "${videoProfile}
echo "video level         : "${videoLevel}
echo "video bitrate       : "${videoBitRate}
echo "video Frame rate    : "${videoFrameRate}
echo "video resolution    : "${videoResolution}
echo "video aspect ration : "${videoAspectRation}
echo "video ref frames    : "${videoRefFrame}
echo "audio codec         : "${audioCodec}
echo "audio profile       : "${audioProfile}
echo "audio sampling rate : "${audioSamplingRate}
echo "audio channels      : "${audioChannels}
echo "--------------------------------------"
command="./ffmpeg -i "${1}" -c:v "${videoCodec}" "${videoMode}" -refs "${videoRefFrame}" -b-pyramid none -profile:v "${videoProfile}" -level "${videoLevel}" -b:v "${videoBitRate}" -r "${videoFrameRate}" -s "${videoResolution}" -aspect "${videoAspectRation}" -c:a "${audioCodec}" -profile:a "${audioProfile}" -ar "${audioSamplingRate}"  -ac "${audioChannels}" -t "${durationLimit}" -f "${outFormat}" "${2}" -y"

通过以上方法转码后使用MediaInfo软件进行视频信息的查看,可以看到视频信息参数值都是转码后的值了。ffmpeg的功能非常强大,这里使用的脚本是北京分公司那边提供的,在进行部分修改过后可以达到我们需要的要求。


上面的shell脚本可以根据指定参数进行视频的转码,但是有个小问题,就是每次只能转码一个视频,在视频资源很多的情况下。。。这将是个浩大的工程。所以在此基础上我写了个自动化脚本,回头只要执行这个自动化脚本就可以一次性转码多个视频。这个自动化脚本的功能很简单,就是把转码前文件夹里面的视频文件进行遍历转码,然后存放到转码后的文件夹里面,回头只要将需要转码的视频拷贝到转码前文件夹里面,运行自动化脚本就可以了。由于这个自动化脚本是我自己写的。。所以就可以简单粗暴的直接上代码了。。。。。。

#!/bin/sh
OLD_IFS=$IFS
IFS=$'\n'
videoResolution=1920x1080
audio=
function checkVideo()
{
   for line in `cat ../temp.txt`
   do
    #时长
    if [[ $line =~ "Duration" ]];then
	echo $line >> string.txt
	dura=`awk -F"," '{print $1}' string.txt | awk -F":" '{print ($4+0)}'`
	rm -rf string.txt
	if [ `expr "$dura" \< 15.1` -eq 0 ];then
	  echo "---------->视频时间超出15秒..."
	  exit 1
	else
	   echo "---------->视频时长为${dura}"
	fi
     fi
     #分辨率
     if [[ $line =~ "Video" ]];then
	IFS=","
	array=($line)
	IFS=$'\n'
	for i in ${array[@]}
	 do
	  if [[ $i =~ "1920x1080" ]];then
	    videoResolution=1920x1080
      	  elif [[ $i =~ "1280x720" ]];then
	   videoResolution=1280x720
	  fi
	done
      fi
     #音频aac判断
     if [[ $line =~ "Audio" ]];then
	echo $line >> string.txt
	audio=`awk -F":" '{print $4}' string.txt`
	rm -rf string.txt
	if [[ $audio =~ "aac" ]];then
	   audio="aac"
	else
	   echo "---------->音频格式错误,应为aac..."
	   exit 1
	fi
     fi
     done
}

cd ./aftertrans
echo "---------->正在清除aftertrans目录的数据..."
rm -rf after_*
echo "---------->数据清除完成..."
cd ../beforetrans
echo "---------->进入beforetrans目录..."
rm -rf string.txt
echo "---------->即将开始遍历文件进行转码操作..."
for file in `ls`
 do
   temp_file=`basename $file`
   echo "---------->输入文件:$temp_file"
   echo "---------->输出文件:./aftertrans/after_$temp_file"
   echo "---------->当前检测文件:$temp_file "
   ~/transcode-tools/ffmpeg -i $temp_file &> ../temp.txt
   echo "---------->即将对$temp_file 开始检测..."
   checkVideo
   echo "---------->$temp_file 检测完成...即将进行转码"
   echo "---------->"
   echo "------->"
   echo "---->"
   #echo "~/aftertrans/after_`date +%Y%m%d%H%M%S`_$temp_file"
   ~/transcode-tools/transcode_2.sh ~/beforetrans/$temp_file "~/aftertrans/after_`date +%Y%m%d%H%M%S`_$temp_file" $videoResolution
   echo "---------->$temp_file 转码完成了..."
   echo "------->"
   echo "---->"
 done

上面代码中beforetrans是个文件夹,里面存放的是转码前的视频文件,aftertrans文件夹里面存放的是转码后的文件夹,string.txt是个临时文件