前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >FFMPEG-如何对视频按时长切片与压缩

FFMPEG-如何对视频按时长切片与压缩

作者头像
王亚昌
发布2018-08-03 15:54:50
2K0
发布2018-08-03 15:54:50
举报
文章被收录于专栏:王亚昌的专栏

本文介绍如何用ffmpeg开源组件按时长进行切片,举一个例子,一个视频网站,拿到一个时长1.5小时的电影,用户点击播放时,常用的技术方案就是把一个完整的大文件,转码后切成按固定时长的小文件,分发到cdn上去,这样用户就可以实现就近下载,包括拖放等操作,这里面有比较多的技术细节,本文只讨论第一步,按时长切片。

一 获取视频时长

ffmpeg安装后,直接执行ffmpeg -i 文件就可以从内容中获取到时长,如下图所示,其中的Duration就是时长

代码语言:javascript
复制
wangyachangdeMacBook-Pro:ffmpeg wangyachang$ /usr/local/ffmpeg/bin/ffmpeg -i movie.mp4 
ffmpeg version 3.0.2 Copyright (c) 2000-2016 the FFmpeg developers
  built with Apple LLVM version 7.0.2 (clang-700.1.81)
  configuration: --prefix=/usr/local/ffmpeg/ --disable-yasm
  libavutil      55. 17.103 / 55. 17.103
  libavcodec     57. 24.102 / 57. 24.102
  libavformat    57. 25.100 / 57. 25.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 31.100 /  6. 31.100
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'movie.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 1
    compatible_brands: isom
    creation_time   : 2015-11-04 06:54:54
    encoder         : FormatFactory : www.pcfreetime.com
  Duration: 00:03:25.01, start: 0.000000, bitrate: 1101 kb/s
    Stream #0:0(und): Video: mpeg4 (Simple Profile) (mp4v / 0x7634706D), yuv420p, 720x480 [SAR 32:27 DAR 16:9], 977 kb/s, 24 fps, 24 tbr, 24k tbn, 24 tbc (default)
    Metadata:
      creation_time   : 2015-11-04 06:54:54
      handler_name    : video
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 122 kb/s (default)
    Metadata:
      creation_time   : 2015-11-04 06:54:54
      handler_name    : sound

不过上面的信息是打印到标准出错的,用下面的命令可以取到对应信息

代码语言:javascript
复制
wangyachangdeMacBook-Pro:ffmpeg wangyachang$ /usr/local/ffmpeg/bin/ffmpeg -i movie.mp4 2>&1 | grep Duration
  Duration: 00:03:25.01, start: 0.000000, bitrate: 1101 kb/s

通过awk可以方便的取出时\分\秒。

二 切片

通过下面的命令可以实现切片。

/usr/local/ffmpeg/bin/ffmpeg -ss START  -t LENGTH -i INPUTFILE  -vcodec copy -acodec copy OUTFILE

举一个例子,如果要把一个3分钟的文件,按每1分钟切一个片,可以用下面的方式切成三个文件

/usr/local/ffmpeg/bin/ffmpeg -ss 0 -t 00:01:00 -i movie.mp4  -vcodec copy -acodec copy movie-1.mp4

/usr/local/ffmpeg/bin/ffmpeg -ss 00:01:00 -t 00:02:00 -i movie.mp4  -vcodec copy -acodec copy movie-2.mp4

/usr/local/ffmpeg/bin/ffmpeg -ss 00:02:00 -t 00:03:00 -i movie.mp4  -vcodec copy -acodec copy movie-3.mp4

执行后,结果如下所示:

代码语言:javascript
复制
ffmpeg version 3.0.2 Copyright (c) 2000-2016 the FFmpeg developers
  built with Apple LLVM version 7.0.2 (clang-700.1.81)
  configuration: --prefix=/usr/local/ffmpeg/ --disable-yasm
  libavutil      55. 17.103 / 55. 17.103
  libavcodec     57. 24.102 / 57. 24.102
  libavformat    57. 25.100 / 57. 25.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 31.100 /  6. 31.100
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'movie.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 1
    compatible_brands: isom
    creation_time   : 2015-11-04 06:54:54
    encoder         : FormatFactory : www.pcfreetime.com
  Duration: 00:03:25.01, start: 0.000000, bitrate: 1101 kb/s
    Stream #0:0(und): Video: mpeg4 (Simple Profile) (mp4v / 0x7634706D), yuv420p, 720x480 [SAR 32:27 DAR 16:9], 977 kb/s, 24 fps, 24 tbr, 24k tbn, 24 tbc (default)
    Metadata:
      creation_time   : 2015-11-04 06:54:54
      handler_name    : video
    Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 122 kb/s (default)
    Metadata:
      creation_time   : 2015-11-04 06:54:54
      handler_name    : sound
File 'movie-1.mp4' already exists. Overwrite ? [y/N] y
Output #0, mp4, to 'movie-1.mp4':
  Metadata:
    major_brand     : isom
    minor_version   : 1
    compatible_brands: isom
    encoder         : Lavf57.25.100
    Stream #0:0(und): Video: mpeg4 ( [0][0][0] / 0x0020), yuv420p, 720x480 [SAR 32:27 DAR 16:9], q=2-31, 977 kb/s, 24 fps, 24 tbr, 24k tbn, 24k tbc (default)
    Metadata:
      creation_time   : 2015-11-04 06:54:54
      handler_name    : video
    Stream #0:1(und): Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo, 122 kb/s (default)
    Metadata:
      creation_time   : 2015-11-04 06:54:54
      handler_name    : sound
Stream mapping:
  Stream #0:0 -> #0:0 (copy)
  Stream #0:1 -> #0:1 (copy)
Press [q] to stop, [?] for help
frame= 1440 fps=0.0 q=-1.0 Lsize=    8435kB time=00:01:00.00 bitrate=1151.7kbits/s speed=1.59e+03x    
video:7480kB audio:920kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.419454%

最后,分享一个开源的脚本,做了一些优化,十分感谢原作者

代码语言:javascript
复制
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
#本脚本使用ffmpeg分割音视频文件,分割过程不进行转码或压缩 

import subprocess
import re
import os
import math
from optparse import OptionParser


length_regexp = 'Duration: (\d{2}):(\d{2}):(\d{2})\.\d+,'
re_length = re.compile(length_regexp)

def main():

    (filename, split_length, file_list) = parse_options()
    if split_length <= 0:
        print "Split length can't be 0"
        raise SystemExit

    output = subprocess.Popen("/usr/local/ffmpeg/bin/ffmpeg -i '"+filename+"' 2>&1 | grep 'Duration'", 
                            shell = True,
                            stdout = subprocess.PIPE
                            ).stdout.read()
    print output
    matches = re_length.search(output)
    if matches:
        video_length = int(matches.group(1)) * 3600 + \
                        int(matches.group(2)) * 60 + \
                        int(matches.group(3))
        print "Video length in seconds: "+str(video_length)
    else:
        print "Can't determine video length."
        raise SystemExit

    split_count = int(math.ceil(video_length/float(split_length)))
    if(split_count == 1):
        print "Video length is less then the target split length."
        raise SystemExit

    print split_count, video_length, split_length

    if os.path.exists(file_list):
	    os.remove(file_list)

    fp = open(file_list, "wb")
    split_cmd = "/usr/local/ffmpeg/bin/ffmpeg -i '"+filename+"' -vcodec copy "
    for n in range(0, split_count):
        split_str = ""
        if n == 0:
            split_start = 0
        else:
            split_start = split_length * n
        
	output_filename = filename[:-4] + "-" + str(n) + "." + filename[-3:]
        split_str += " -ss "+str(split_start)+" -t "+str(split_length) + \
                    " '"+output_filename+ \
                    "'"
        print "About to run: "+split_cmd+split_str
	fp.write(output_filename+"\n")
        output = subprocess.Popen(split_cmd+split_str, shell = True, stdout =
                               subprocess.PIPE).stdout.read()
    fp.close()


def parse_options():
    parser = OptionParser()    
    
    parser.add_option("-f", "--file",
                        dest = "filename",
                        help = "file to split, for example sample.avi",
                        type = "string",
                        action = "store"
                        )
    parser.add_option("-s", "--split-size",
                        dest = "split_size",
                        help = "split or chunk size in seconds, for example 10",
                        type = "int",
                        action = "store"
                        )
    parser.add_option("-o", "--file-list",
                        dest = "file_list",
                        help = "output file_list",
                        type = "string",
                        action = "store"
                        )
    (options, args) = parser.parse_args()
    
    if options.filename and options.split_size and options.file_list:

        return (options.filename, options.split_size, options.file_list)

    else:
        parser.print_help()
        raise SystemExit

if __name__ == '__main__':

    try: 
        main()
    except Exception, e:
        print "Exception occured running main():"
        print str(e)

三 压缩

/usr/local/ffmpeg/bin/ffmpeg  -i "2.4_mission.mp4" -vcodec libx264 -s 1920X1080 -vf "movie=stark.png [watermark]; [in][watermark] overlay=main_w-overlay_w-10:10 [out]"  -acodec copy "2.4_1080P.mp4"

压缩效果还不错,99m的原文件,压缩后画质未变的情况下,体积变成14m。

参考文献:

http://icephoenix.us/notes-for-myself/auto-splitting-video-file-in-equal-chunks-with-ffmpeg-and-python/

http://blog.itpub.net/29754888/viewspace-1383562/ http://blog.csdn.net/dotphoenix/article/details/9714773

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2016年06月24日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档