Python:如何加入多个视频文件

时间:2013-07-16 05:53:24

标签: python-2.7

我对python比较陌生,所以如果这是一个之前已经回答的问题,请耐心等待。我正在编写一个python脚本来合并几个视频文件,我试图在线搜索答案但无济于事。我想知道我是否可以编写python脚本而不使用ffmpeg只是程序的纯python代码。我尝试过类似的东西,但它并没有真正起作用

fo=open("outfile","wb")
fo.write(open("infile1").read())
fo.write(open("infile2").read())
fo.close()

3 个答案:

答案 0 :(得分:1)

我不确定,如果你可以追加另一个视频文件。每个videofile都有一个特定的格式,包括标题,曲目等。看看http://en.wikipedia.org/wiki/MPEG_transport_stream。但是,使用ffmpeg,您可以这样做:

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

度过愉快的一天;)

答案 1 :(得分:0)

  

我想知道我是否可以在不使用ffmpeg的情况下编写python脚本   只是纯粹的蟒蛇

没有。您需要了解编解码器才能合并视频内容(包括音轨),然后将其打包到相应的容器中。这不是一个微不足道的任务,这就是为什么有库自动化它。

答案 2 :(得分:0)

我的用例需要将分布在16个文件夹中的一堆.mp3文件串联为每个文件夹一个.mp3文件。发现ffmpeg.orgffmpeg-python上的文档有些缺乏或令人困惑...

我期望能够创建ffmpeg对象,然后将列表传递或将单个路径对象迭代到ffmpeg的输入中,然后在输入对象上运行concat,然后输出到目标,但是ffmpeg.input(<FILE LIST>).concat(acodec='copy').output(<OUTFILE>).run()最终变成了一个巨大的失败球……直到我碰到@CCfVssZijV2X的帖子,其中包含concat输入格式,这对我来说真是不妙。

下面的脚本将基本路径作为输入。假定基本路径包含的文件夹包含多个音频文件,这些音频文件将作为基本路径中的文件夹名称串联到每个文件夹中。.mp3。

如果基本路径仅包含一个文件夹,则文件夹批处理将直接发送到combin_audio,否则批处理列表将发送到多处理功能,该功能会将每个批处理分配到您拥有或可用的多个核上。

虽然我确定python包装器某些问题的原因与我的无知和对ffmpeg的不熟悉有关,但我希望这可以对某人有所帮助,或者使他们开始走上正确的道路用例。

from concurrent.futures import ProcessPoolExecutor
from pathlib import Path as p
from os import cpu_count
import ffmpeg

class FFConcat:

    def __init__(self, path, check_files=False):

        self.check_files = check_files
        self.path = p(path)
        self.cores = cpu_count()
        self.batches = []

    def file_check(self):
        '''
        Optional:
        Iterates over folders in path, renames with leading zero for sorting if missing.
        '''
        for folder in sorted(self.path.iterdir()):
            # Folder names were originally "Folder Name - [Disk 1]"
            disk_number = folder.stem.split()[-1].strip(']')
            if len(disk_number) == 1:
                folder.rename('{}/Folder Name - Disk 0{}'.format(self.path, disk_number))
            elif len(disk_number) == 2:
                folder.rename('{}/Folder Name - Disk {}'.format(self.path, disk_number))

    def file_batch(self):
        '''
        Iterates over folders in path creating a list. Converts list into string format
        which is combined with resulting output filename in a dict and added to
        batch list.
        '''
        print('Batching audio files by folder.')
        for folder in sorted(self.path.iterdir()):
            # Use folder names as concat output name for final file.
            outfile = (self.path/'{}.mp3'.format(folder.stem)).as_posix()
            tracks = []
            # Create a list of sorted tracks in folder.
            for track in sorted(folder.iterdir()):
                tracks.append(track.as_posix())
            print('Located {} audio files in \"{}\"'.format(len(tracks), folder.stem))
            # Format file list in string format which ffmpeg will accept via input.
            file_list = '|'.join(_ for _ in tracks)
            # Generate list of dictionaries containing the file list and output filemame
            self.batches.append({
                                'file_list': file_list,
                                'outfile': outfile
                                })

    def combine_audio(self, batch):
        '''
        Input: single dictionary containing a string formatted file list for each folder
        and output filename. Converts list into ffmpeg input concat object. Runs object
        with audio codec copy concatenating files within folder into single file.
        '''
        print('Starting concat for: {}'.format(batch['outfile']))
        tracks = ffmpeg.input('concat:{}'.format(batch['file_list']))
        tracks.output(batch['outfile'], acodec='copy').run()
        print('Completed concat for: {}'.format(batch['outfile']))

    def mp(self, function, iterable):
        '''
        Input: combine_audio function and batch list.
        Sets max workers depending on iterable length and core count.
        '''
        if len(iterable) >= self.cores:
            workers = self.cores
        elif len(iterable) < self.cores:
            workers = len(iterable)
        with ProcessPoolExecutor(max_workers=workers) as p:
            p.map(function, iterable)

    def run(self):

        if self.check_files:
            self.file_check()

        self.file_batch()

        if len(self.batches) == 1:
            print('One batch found. Sending directly to concatenator.')
            self.combine_audio(self.batches[0])
        elif len(self.batches) > 1:
            print('Sending {} batches to multi-processing.'.format(len(self.batches)))
            self.mp(self.combine_audio, self.batches)

concat = FFConcat(path='Base path containing folders with tracks')
concat.run()