Python实现多个视频合成一个视频的功能

作者:剑客阿良_ALiang 时间:2021-10-31 12:57:44 

前言

本文提供将多个视频拼接为一个视频的Python工具代码,其中有一些限制条件,下面的代码说明会提到。

环境依赖

ffmpeg环境安装,可以参考:windows ffmpeg安装部署

本文主要使用到的不是ffmpeg,而是ffprobe也在上面这篇文章中的zip包中。

Python实现多个视频合成一个视频的功能

ffmpy安装:


pip install ffmpy -i https://pypi.douban.com/simple

代码

不废话了,上代码。


#!/user/bin/env python
# coding=utf-8
"""
@project : csdn
@author  : 剑客阿良_ALiang
@file   : concat_video.py
@ide    : PyCharm
@time   : 2021-12-23 15:23:16
"""

from ffmpy import FFmpeg
import os
import uuid
import subprocess

# 视频拼接
def concat(video_list: list, output_dir: str):
   if len(video_list) == 0:
       raise Exception('video_list can not empty')
   _ext = check_format(video_list)
   _fps = check_fps(video_list)
   _result_path = os.path.join(
       output_dir, '{}{}'.format(
           uuid.uuid1().hex, _ext))
   _tmp_config = make_tmp_concat_config(video_list, output_dir)
   ff = FFmpeg(inputs={'{}'.format(_tmp_config): '-f concat -safe 0 -y'}, outputs={
       _result_path: '-c copy'})
   print(ff.cmd)
   ff.run()
   os.remove(_tmp_config)
   return _result_path

# 构造拼接所需临时文件
def make_tmp_concat_config(video_list: list, output_dir: str):
   _tmp_concat_config_path = os.path.join(output_dir, '{}.txt'.format(uuid.uuid1().hex))
   with open(_tmp_concat_config_path, mode='w', encoding='utf-8') as f:
       f.writelines(list(map(lambda x: 'file {}\n'.format(x), video_list)))
   return _tmp_concat_config_path

# 校验每个视频的格式
def check_format(video_list: list):
   _video_format = ''
   for x in video_list:
       _ext = os.path.splitext(x)[-1]
       if _video_format == '' and _ext != '':
           _video_format = _ext
           continue
       if _video_format != '' and _ext == _video_format:
           continue
       if _video_format != '' and _ext != _video_format:
           raise Exception('Inconsistent video format')
   return _video_format

# 校验每个视频的fps
def check_fps(video_list: list):
   _video_fps = 0
   for x in video_list:
       _fps = get_video_fps(x)
       if _video_fps == 0 and _fps:
           _video_fps = _fps
           continue
       if _video_fps != 0 and _fps == _video_fps:
           continue
       if _video_fps != '' and _fps != _video_fps:
           raise Exception('Inconsistent video fps')
   if _video_fps == 0:
       raise Exception('video fps error')
   return _video_fps

# 获取视频fps
def get_video_fps(video_path: str):
   ext = os.path.splitext(video_path)[-1]
   if ext != '.mp4' and ext != '.avi' and ext != '.flv':
       raise Exception('format not support')
   ffprobe_cmd = 'ffprobe -v error -select_streams v -of default=noprint_wrappers=1:nokey=1 -show_entries stream=r_frame_rate {}'
   p = subprocess.Popen(
       ffprobe_cmd.format(video_path),
       stdout=subprocess.PIPE,
       stderr=subprocess.PIPE,
       shell=True)
   out, err = p.communicate()
   print("subprocess 执行结果:out:{} err:{}".format(out, err))
   fps_info = str(out, 'utf-8').strip()
   if fps_info:
       if fps_info.find("/") > 0:
           video_fps_str = fps_info.split('/', 1)
           fps_result = int(int(video_fps_str[0]) / int(video_fps_str[1]))
       else:
           fps_result = int(fps_info)
   else:
       raise Exception('get fps error')
   return fps_result

if __name__ == '__main__':
   print(concat(['D:/tmp/100.mp4', 'D:/tmp/101.mp4'], 'C:/Users/huyi/Desktop'))

代码说明

1、主要拼接方法为concat,入参分别为:视频列表、输出目录。

2、该视频拼接命令对视频本身有所限制,需要保证都是相同格式的视频,其次是每个视频的fps得一致,不然最终合成的视频会无法打开或者出现花屏现象。

3、临时的拼接文件会在使用后删除。

4、最终输出的文件名为了保证唯一使用uuid。

验证一下

下面是我准备的两个视频:

Python实现多个视频合成一个视频的功能Python实现多个视频合成一个视频的功能

执行结果


PyDev console: starting.
Python 3.6.13 |Anaconda, Inc.| (default, Mar 16 2021, 11:37:27) [MSC v.1916 64 bit (AMD64)] on win32
runfile('D:/spyder/csdn/tool/concat_video.py', wdir='D:/spyder/csdn/tool')
subprocess 执行结果:out:b'25/1\r\n' err:b''
subprocess 执行结果:out:b'25/1\r\n' err:b''
ffmpeg -f concat -safe 0 -y -i C:/Users/huyi/Desktop\6d02df4b63d111eca6eee454e8bf1461.txt -c copy C:/Users/huyi/Desktop\6d02df4a63d111ec9dbbe454e8bf1461.mp4
ffmpeg version n4.3.1-20-g8a2acdc6da Copyright (c) 2000-2020 the FFmpeg developers
 built with gcc 9.3-win32 (GCC) 20200320
 configuration: --prefix=/ffbuild/prefix --pkg-config-flags=--static --pkg-config=pkg-config --cross-prefix=x86_64-w64-mingw32- --arch=x86_64 --target-os=mingw32 --enable-gpl --enable-version3 --disable-debug --enable-iconv --enable-zlib --enable-libxml2 --enable-libfreetype --enable-libfribidi --enable-gmp --enable-lzma --enable-fontconfig --enable-libvmaf --disable-vulkan --enable-libvorbis --enable-amf --enable-libaom --enable-avisynth --enable-libdav1d --enable-ffnvcodec --enable-cuda-llvm --disable-libglslang --enable-libass --enable-libbluray --enable-libmp3lame --enable-libopus --enable-libtheora --enable-libvpx --enable-libwebp --enable-libmfx --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-librav1e --enable-schannel --enable-sdl2 --enable-libsoxr --enable-libsrt --enable-libtwolame --enable-libvidstab --enable-libx264 --enable-libx265 --enable-libxvid --enable-libzimg --extra-cflags=-DLIBTWOLAME_STATIC --extra-cxxflags= --extra-ldflags=-pthread --extra-libs=-lgomp
 libavutil      56. 51.100 / 56. 51.100
 libavcodec     58. 91.100 / 58. 91.100
 libavformat    58. 45.100 / 58. 45.100
 libavdevice    58. 10.100 / 58. 10.100
 libavfilter     7. 85.100 /  7. 85.100
 libswscale      5.  7.100 /  5.  7.100
 libswresample   3.  7.100 /  3.  7.100
 libpostproc    55.  7.100 / 55.  7.100
[mov,mp4,m4a,3gp,3g2,mj2 @ 000001de4a7aebc0] Auto-inserting h264_mp4toannexb bitstream filter
Input #0, concat, from 'C:/Users/huyi/Desktop\6d02df4b63d111eca6eee454e8bf1461.txt':
 Duration: N/A, start: -0.064000, bitrate: 1098 kb/s
   Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 69 kb/s
   Metadata:
     handler_name    : SoundHandler
   Stream #0:1(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1080x1920, 1028 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc
   Metadata:
     handler_name    : VideoHandler
Output #0, mp4, to 'C:/Users/huyi/Desktop\6d02df4a63d111ec9dbbe454e8bf1461.mp4':
 Metadata:
   encoder         : Lavf58.45.100
   Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p, 1080x1920, q=2-31, 1028 kb/s, 25 fps, 25 tbr, 12800 tbn, 12800 tbc
   Metadata:
     handler_name    : VideoHandler
   Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 16000 Hz, mono, fltp, 69 kb/s
   Metadata:
     handler_name    : SoundHandler
Stream mapping:
 Stream #0:1 -> #0:0 (copy)
 Stream #0:0 -> #0:1 (copy)
Press [q] to stop, [?] for help
[mov,mp4,m4a,3gp,3g2,mj2 @ 000001de4a7aebc0] Auto-inserting h264_mp4toannexb bitstream filter
[mp4 @ 000001de4acdabc0] Non-monotonous DTS in output stream 0:1; previous: 6176768, current: 6176608; changing to 6176769. This may result in incorrect timestamps in the output file.
frame=22199 fps=0.0 q=-1.0 Lsize=  119649kB time=00:14:48.05 bitrate=1103.7kbits/s speed=2.41e+03x    
video:111571kB audio:7524kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.465183%
C:/Users/huyi/Desktop\6d02df4a63d111ec9dbbe454e8bf1461.mp4

结果验证

Python实现多个视频合成一个视频的功能

来源:https://blog.csdn.net/zhiweihongyan1/article/details/122111988

标签:Python,视频,合成
0
投稿

猜你喜欢

  • Python实战之自动发送邮件的实现

    2023-10-18 15:09:43
  • Python骚操作完美实现短视频伪原创

    2023-09-18 08:16:55
  • python通过imaplib模块读取gmail里邮件的方法

    2023-11-03 04:24:42
  • Golang设计模式工厂模式实战写法示例详解

    2024-05-25 15:11:42
  • Go与C语言的互操作实现

    2024-02-04 08:39:28
  • springboot 启动时初始化数据库的步骤

    2024-01-26 18:32:57
  • 百度留言本js 大家可以参考下

    2024-04-16 09:31:55
  • Python中如何添加自定义模块

    2023-06-09 23:24:38
  • Navicat for MySQL 15注册激活详细教程

    2024-01-19 00:05:16
  • pycharm解决关闭flask后依旧可以访问服务的问题

    2023-12-27 06:39:27
  • python标准库sys和OS的函数使用方法与实例详解

    2022-06-24 20:22:42
  • JS的编译和执行顺序

    2009-02-01 18:42:00
  • PHP 二维数组根据某个字段排序的具体实现

    2023-11-20 05:21:13
  • php获取域名的google收录示例

    2022-08-22 07:26:48
  • Python算法应用实战之栈详解

    2022-08-22 21:56:10
  • python 异常的传递性及主动抛出学习

    2021-03-19 05:02:38
  • MySQL设置global变量和session变量的两种方法详解

    2024-01-20 23:34:16
  • Oracle中字符串连接的实现方法

    2024-01-15 11:59:24
  • Facebook开源一站式服务python时序利器Kats详解

    2023-11-13 18:29:13
  • javascript中利用柯里化函数实现bind方法【推荐】

    2024-05-02 17:29:26
  • asp之家 网络编程 m.aspxhome.com