如何使用MoviePy批量处理视频文件夹

时间:2017-04-12 22:41:25

标签: python moviepy

我写了一个MoviePy脚本,它接受输入视频,进行一些处理,并输出一个视频文件。我想在整个视频文件夹中运行它。任何帮助或指示都表示赞赏。

这是我试过的......

for f in *; do python resize.py $f; done

和resize.py源代码在这里:

from moviepy.editor import *

clip = VideoFileClip(input)

clip1 = clip.rotate(270)

clip2 = clip1.crop(x_center=540,y_center=960,width=1080,height=608)

clip3 = clip2.resize(width=1920)

clip3.write_videofile(output,codec='libx264')

真的不确定在我的.py文件中输入“输入”和“输出”的内容。

谢谢, 埃文

2 个答案:

答案 0 :(得分:0)

我知道你有答案on Github,但我会添加自己的解决方案。

首先,您需要将代码放在函数中:

def process_video(input):
    """Parameter input should be a string with the full path for a video"""

    clip = VideoFileClip(input, output)

    clip1 = clip.rotate(270)

    clip2 = clip1.crop(x_center=540,y_center=960,width=1080,height=608)

    clip3 = clip2.resize(width=1920)

    clip3.write_videofile(output,codec='libx264')

然后,您可以拥有一个返回文件路径列表的函数,以及一个与上述函数一起使用的最终文件名列表(请注意,最终文件名将与原始文件名相同,但具有“输出“在前面”:

import os
def get_video_paths(folder_path):
    """ 
    Parameter folder_path should look like "Users/documents/folder1/"
    Returns a list of complete paths
    """
    file_name_list = os.listdir(folder_path)

    path_name_list = []
    final_name_list = []
    for name in file_name_list:
        # Put any sanity checks here, e.g.:
        if name == ".DS_Store":
            pass
        else:
            path_name_list.append(folder_path + name)
            # Change the format of the output file names below
            final_name_list.append(folder_path + "output" + name)  
    return path_name_list, final_name_list

最后,在底部,我们获取输入文件夹,并使用上述两个功能:

if __name__ == "__main__":
    video_folder = input("What folder would you like to process? ")
    path_list, final_name_list = get_video_paths(video_folder)
    for path, name in zip(path_list, final_name_list):
        process_video(path, name)
    print("Finished")

请注意,因为如果文件夹中的任何文件无法作为电影读取,则会崩溃。例如,在Mac上,操作系统会在每个文件夹中放置一个“.DS_Store”文件,这会使程序崩溃。我把一个区域用于理智检查以忽略某些文件名。

完整代码:

import os

from moviepy.editor import *


def process_video(input, output):
    """Parameter input should be a string with the full path for a video"""

    clip = VideoFileClip(input)

    clip1 = clip.rotate(270)

    clip2 = clip1.crop(x_center=540,y_center=960,width=1080,height=608)

    clip3 = clip2.resize(width=1920)

    clip3.write_videofile(output,codec='libx264')


def get_video_paths(folder_path):
    """ 
    Parameter folder_path should look like "Users/documents/folder1/"
    Returns a list of complete paths
    """
    file_name_list = os.listdir(folder_path)

    path_name_list = []
    final_name_list = []
    for name in file_name_list:
        # Put any sanity checks here, e.g.:
        if name == ".DS_Store":
            pass
        else:
            path_name_list.append(folder_path + name)
            final_name_list.append(folder_path + "output" + name)
    return path_name_list, final_name_list

if __name__ == "__main__":
    video_folder = input("What folder would you like to process? ")
    path_list, final_name_list = get_video_paths(video_folder)
    for path, name in zip(path_list, final_name_list):
        process_video(path, name)
    print("Finished")

答案 1 :(得分:0)

我在Github issue #542上回复了,但我将其复制到此处以供将来参考!

首先,下面的例子不是铁定的,但它应该做你需要的。 您可以通过以下方式实现此目的:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""Convert all media assets located in a specified directory."""
import glob
import os
from optparse import OptionParser

from moviepy.editor import VideoFileClip


def get_dir_files(dir_path, patterns=None):
    """Get all absolute paths for pattern matched files in a directory.

    Args:
        dir_path (str): The path to of the directory containing media assets.
        patterns (list of str): The list of patterns/file extensions to match.

    Returns:
        (list of str): A list of all pattern-matched files in a directory.
    """
    if not patterns or type(patterns) != list:
        print('No patterns list passed to get_dir_files, defaulting to patterns.')
        patterns = ['*.mp4', '*.avi', '*.mov', '*.flv']

    files = []
    for pattern in patterns:
        dir_path = os.path.abspath(dir_path) + '/' + pattern
        files.extend(glob.glob(dir_path))

    return files

def modify_clip(path, output):
    """Handle conversion of a video file.

    Args:
        path (str): The path to the directory of video files to be converted.
        output (str): The filename to associate with the converted file.
    """
    clip = VideoFileClip(path)
    clip = clip.rotate(270)
    clip = clip.crop(x_center=540, y_center=960, width=1080, height=608)
    clip = clip.resize(width=1920)

    clip.write_videofile(output, codec='libx264')
    print('File: {} should have been created.'.format(output))


if __name__ == '__main__':
    status = 'Failed!'
    parser = OptionParser(version='%prog 1.0.0')
    parser.add_option('-p', '--path', action='store', dest='dir_path',
                      default='.', type='string',
                      help='the path of the directory of assets, defaults to .')

    options, args = parser.parse_args()
    print('Running against directory path: {}'.format(options.dir_path))
    path_correct = raw_input('Is that correct?').lower()

    if path_correct.startswith('y'):
        dir_paths = get_dir_files(options.dir_path)
        for dir_path in dir_paths:
            output_filename = 'converted_' + os.path.basename(dir_path)
            modify_clip(path=dir_path, output=output_filename)

        status = 'Successful!'

    print('Conversion {}'.format(status))

通过上面的示例,您只需将其放入要转换的资产目录中并运行:python this_file.py它应该在同一目录中为您转换文件,其名称前缀为:{{ 1}}

同样,您可以将该文件放在任何位置并针对绝对路径运行它: converted_它会转换所有带扩展名的文件:python this_file.py -p /Users/thisguy/media

无论哪种方式,如果您有任何问题(或者如果这可以解决您的问题),请告诉我,我会尽力帮助您!

感谢您使用moviepy!