美文网首页
ffmpeg 裁剪、切割视频

ffmpeg 裁剪、切割视频

作者: 叁点水 | 来源:发表于2019-04-13 18:41 被阅读0次

    前言

    之前写过一篇用 shell 脚本与 ffmpeg 结合,批量把视频切割成指定时长的多个视频片断,当时写的那个脚本只支持这一个小功能,写的粗糙,原视频的总时长也没有获取到,还需要手动填写。

    这次在那个的基础上添加了自动获取视频分辨率、时长,并且按指定的宽高裁剪视频的中间部分的画面(在这个 demo 中是这样设置,可以根据需要改为指定部分的画面,原理就是计算指定画面在原视频中的比例)的功能。

    正文

    1. 首先要先获取文件夹中的文件,并且判断哪些文件是视频文件
    # 获取该脚本文件所在的文件夹中的所有文件名
    path=$1
    files=$(ls $path)</pre>
     
    # 根据文件的格式判断文件是否是视频文件,这里是直接写死的,如果有其他的格式,这里就要手动更换,其实也可以自动获取,与获取视频时宽高是类似的,这里就不写了。
        type=".mp4"
        if [[ $filename =~ $type ]]</pre>
    
    1. 这里开始使用 ffmpeg ,把视频文件的信息以 json 的格式提取出来,在这个 demo 中把视频的信息保存到了 videoinfo 文件中
       ffprobe -print_format json -show_streams $filename > videoinfo</pre>
    
    1. 接下来就是从 videoinfo 文件的 json 字符串中把我们要的宽高以及时长提取出来
     # 这一段执行之后,videowidth 的值就是视频的宽
        while  read line 
         do
         #statements
         if [[ $line =~ 'width' ]]; then
         #statements
         # 这里用了 awk 的方法提取字符串的一部分
         videowidth=`echo $line | awk -F: '{print $2}' | awk -F, '{print $1}'`
         echo $line
         echo 'width' + $videowidth
         break
         fi
         done < videoinfo</pre>
    

    用下面的这种循环方法也可以得到视频的宽,但是这样的话,videowidth 的值只能在这个循环里有用,在循环外面这个值是获取不到的,而上面的那种写法叫重定向,就可以解决这个问题。

      cat videoinfo | while  read line 
        do
         #statements
         if [[ $line =~ 'width' ]]; then
         #statements
         videowidth=`echo $line | awk -F: '{print $2}' | awk -F, '{print $1}'`
         echo $line
         echo 'width' + $videowidth
    
         # echo "$videowidth"
         break
        ​
         fi
        done</pre>
    

    类似的视频的高和时长也是用同样的方法可以获取到。就不贴详细代码了。

    1. 我们需要的信息都获取到之后,就开始对视频进行处理了,这里我们的需求是把裁剪视频中间的画面,并切割成指定的时长。这里我们分成两步:
      1. 第一步:把视频先进行裁剪
        # 这个是 ffmpeg 的命令,裁剪的功能主要是 crop 这个命令,它的参数分别代表的是:输出视频的宽:输入出视频的高:裁剪的起始点的 x 的位置:裁剪起始点的 y 的位置。
            # 这四个值可以根据需要去计算
            ffmpeg -i $filename -strict -2 -vf  crop=$($w:$h:$x:0)  $filename+out.mp4 
     </pre>
    
    1. 第二步:把裁剪后的视频切割成指定的时长
         while [ $endTime -le $duration ]; do
             #statements
             i=$[$i+1]
             endTime=$[$startTime+4]
             # 切割视频的时长
             ffmpeg -i /Users/limiao/Desktop/video/$filename+out.mp4  -ss $startTime -to $endTime -acodec copy -vcodec copy outvideo/$filename+$i.mp4
             startTime=$[endTime]
            ​
             done</pre>
    

    总结

    到此,想要实现的功能就都实现了。在实现的过程中有几个问题纠缠了挺久的。

    1. 拿到 json 字符串后,如何从这里拿到我们需要的视频的宽高和时长?

      百度了一些,最后确定的文案是使用 awk,把 json 字符串根据一定的规则切分,最终留下我们要的值。

      用完之后,我觉得 awk 是一个挺有意思的东西,还是值得研究一下的。

    2. 循环的重定向

      刚开始的写的时候,只写了一个小例子测试的时候是没问题的,但一放到正式的文件中要用的时候,那个值就获取不到了,也是查了很多,才找到原因。这两种方式的区别也还有待研究。

    3. 在设置 ffmpeg 中的 crop 参数时,刚开始的写法是这样的

      crop=$w:$h:$x:0</pre>
    

    运行之后提示的错误是参数错误:只有三个参数,后来改为

      crop=$($w:$h:$x:0) </pre>
    

    这样就对了,参数不管是什么它都是一个整体,要使用一个整体去引用。

    代码虽少,但包含的东西挺多的,也弄了好多天,找了很多资料,这些东西基本都是现学现卖,根据需要有目的的学习,效率还挺不错的。

    查看全部文件

    相关文章

      网友评论

          本文标题:ffmpeg 裁剪、切割视频

          本文链接:https://www.haomeiwen.com/subject/xgyrwqtx.html