FFMpeg剪辑视频

作者: 老鼠AI大米_Java全栈 | 来源:发表于2019-12-03 18:12 被阅读0次

    网上有很多视频剪辑的工具,不过大多收费,免费的不好用,还不如试试FFMPEG,可以通过命令方式实现,也可以使用py脚本优化。

    I.FFmpeg concat 协议

    对于 MPEG 格式的视频,可以直接连接:

    ffmpeg -i "concat:input1.mpg|input2.mpg|input3.mpg" -c copy output.mpg
    

    对于非 MPEG 格式容器,但是是 MPEG 编码器(H.264、DivX、XviD、MPEG4、MPEG2、AAC、MP2、MP3 等),可以包装进 TS 格式的容器再合并。在新浪视频,有很多视频使用 H.264 编码器,可以采用这个方法

    ffmpeg -i input1.flv -c copy -bsf:v h264_mp4toannexb -f mpegts input1.ts
    ffmpeg -i input2.flv -c copy -bsf:v h264_mp4toannexb -f mpegts input2.ts
    ffmpeg -i input3.flv -c copy -bsf:v h264_mp4toannexb -f mpegts input3.ts
    ffmpeg -i "concat:input1.ts|input2.ts|input3.ts" -c copy -bsf:a aac_adtstoasc -movflags +faststart output.mp4
    

    保存 QuickTime/MP4 格式容器的时候,建议加上 -movflags +faststart。这样分享文件给别人的时候可以边下边看。

    II.FFmpeg concat 分离器

    这种方法成功率很高,也是最好的,但是需要 FFmpeg 1.1 以上版本。先创建一个文本文件filelist.txt:

    file 'input1.mkv'
    file 'input2.mkv'
    file 'input3.mkv'
    

    然后:

    ffmpeg -f concat -i filelist.txt -c copy output.mkv
    

    注意:使用 FFmpeg concat 分离器时,如果文件名有奇怪的字符,要在 filelist.txt中转义。

    III.Mencoder 连接文件并重建索引

    这种方法只对很少的视频格式生效。幸运的是,新浪视频使用的 FLV 格式是可以这样连接的。对于没有使用 MPEG 编码器的视频(如 FLV1 编码器),可以尝试这种方法,或许能够成功。

    mencoder -forceidx -of lavf -oac copy -ovc copy -o output.flv input1.flv input2.flv input3.flv
    

    IV. FFmpeg concat 过滤器重新编码(有损)

    语法有点复杂,但是其实不难。这个方法可以合并不同编码器的视频片段,也可以作为其他方法失效的后备措施。

    ffmpeg -i input1.mp4 -i input2.webm -i input3.avi -filter_complex '[0:0] [0:1] [1:0] [1:1] [2:0] [2:1] concat=n=3:v=1:a=1 [v] [a]' -map '[v]' -map '[a]' <编码器选项> output.mkv

    如你所见,上面的命令合并了三种不同格式的文件,FFmpeg concat 过滤器会重新编码它们。注意这是有损压缩。

    [0:0] [0:1] [1:0] [1:1] [2:0] [2:1分别表示第一个输入文件的视频、音频、第二个输入文件的视频、音频、第三个输入文件的视频、音频。concat=n=3:v=1:a=1表示有三个输入文件,输出一条视频流和一条音频流。[v] [a] 就是得到的视频流和音频流的名字,注意在 bash 等 shell 中需要用引号,防止通配符扩展。

    V. py之剪辑

    ffmpeg -i ./plutopr.mp4 -vcodec copy -acodec copy -ss 00:00:10 -to 00:00:15 ./cutout1.mp4 -y
    -ss time_off set the start time offset 设置从视频的哪个时间点开始截取,上文从视频的第10s开始截取
    -to 截到视频的哪个时间点结束。上文到视频的第15s结束。截出的视频共5s.
    如果用-t 表示截取多长的时间如 上文-to 换位-t则是截取从视频的第10s开始,截取15s时长的视频。即截出来的视频共15s.

    注意的地方是:
    如果将-ss放在-i ./plutopr.mp4后面则-to的作用就没了,跟-t一样的效果了,变成了截取多长视频。一定要注意-ss的位置。

    参数解析
    -vcodec copy表示使用跟原视频一样的视频编解码器。
    -acodec copy表示使用跟原视频一样的音频编解码器。

    -i 表示源视频文件
    -y 表示如果输出文件已存在则覆盖。

    import os
    
    def cut(filename, start, end):
        assert os.path.exists(filename) is True, "The soruse file is not exists."
        
        videoname = "./" + filename.split(".")[0] + "1.mp4"
        cmd = "ffmpeg -i {} -vcodec copy -acodec copy -ss {} -to {} {} -y".format(filename,start,end,videoname)
        os.popen(cmd)
        exit()
    
    if __name__ == "__main__":
        file = input("需要截取的视频:")
        start = input("起始时间(HH:MM:SS):")
        end = input("结束时间(HH:MM:SS):")
        cut(file, start, end)
    

    VI.py合并

    视频合并
    先将 mp4 转化为同样编码形式的 ts 流,因为 ts流是可以 concate 的,先把 mp4 封装成 ts ,然后 concate ts 流, 最后再把 ts 流转化为 mp4。

    import glob
    import os
    
    def files(curr_dir = '.', ext = '*.exe'):
        """当前目录下的文件"""
        for i in glob.glob(os.path.join(curr_dir, ext)):
            yield i
    def remove_files(rootdir, ext, show = False):
        """删除rootdir目录下的符合的文件"""
        for i in files(rootdir, ext):
            if show:
                print(i)
            os.remove(i)
    
    def concat(filename, filename2):
        assert os.path.exists(filename) is True, "The soruse file is not exists."
        #create ts files
        videoname1 = filename.split(".")[0] + "-1.ts"
        cmd1 = "ffmpeg -i {} -vcodec copy -acodec copy -vbsf h264_mp4toannexb {} -y".format(filename,videoname1)
        videoname2 = filename2.split(".")[0] + "-2.ts"
        cmd2 = "ffmpeg -i {} -vcodec copy -acodec copy -vbsf h264_mp4toannexb {} -y".format(filename2,videoname2)
        #concate ts files to mp4
        concatFiles = "concat:"+videoname1+"|"+videoname2+"|"
        cmd3 = "ffmpeg -i \"{}\" -c copy {} -y".format(concatFiles,"output-end.mp4")
        print(cmd3)
        cmd = "{} && {} && {} && exit()".format(cmd1, cmd2, cmd3)
        os.system(cmd)
        remove_files('.', '*.ts', show = True)
        exit()
    
    if __name__ == "__main__":
        file = input("需要合并的视频1:")
        file2 = input("需要合并的视频2:")
        concat(file, file2)
    

    相关文章

      网友评论

        本文标题:FFMpeg剪辑视频

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