Python使用ffmpeg合成视频、音频的实现方法

作者:宿者朽命 时间:2022-01-24 17:39:06 

最近有在使用屏幕录制软件录制桌面,在用的过程中突发奇想,使用python能不能做屏幕录制工具,也锻炼下自己的动手能力。
接下准备写使用python如何做屏幕录制工具的系列文章:

录制屏幕制作视频

录制音频

合成视频,音频

基于pyqt5制作可视化窗口

大概上述四个部分,希望自己能够尽快完善,前两篇文章分享了利用opencv制作了屏幕录制部分,利用PyAudio录制音频,本篇文章分享如何使用ffmpeg将同时录制的屏幕录像和音频合成为有声音的屏幕录像。

应用平台

  • windows 10

  • python 3.7

  • ffmpeg

音视频合成

在python合成音视频有很多第三方包,操作方法各有不同,有简易的也有稍微复杂的,

起初也有想过使用moviepy中文文档,其在使用门槛上确实比ffmpeg要小很多,在翻查相关资料后,目前要考虑的事是合并音视频为一个有声音的视频,而且ffmpeg具有录制视频的功能,效果比使用cv2+ImageGrab方式要好,所以采用ffmpeg作为合成工具,ffmpeg.exe下载路径,使用手册 。

python下使用ffmpeg,可以直接调用命令行工具,也可以使用封装的第三包。

pip install ffmpeg-python

使用参数与ffmpeg一致,不同处在于,在使用完后需要键入终止条件以结束ffmpeg的运行。

将cv2的屏幕录制改成ffmpeg录制

import ffmpeg

# 屏幕录制画面大小
width = 1920
height = 1080
# 录制帧率,在cv2录制中,发现帧率比较固定且偏小,主要原因为ImageGrab间隔时间稍长
# 这里可以调整的稍微大一点,当然越大对固件性能越好,推荐在15~60之间(含)
fps = 30
# 录制画面是否包含鼠标,0:不包含,1:包含
# 录制方式为gdigrab模式,包含鼠标在录制过程会看到鼠标频闪的现象,可自行搜索模块插件解决
draw_mouse = 0
# 屏幕画面录制偏移距离
offset_x = 0
offset_y = 0
# 文件名称
filename = 'test.mp4'
# 录制桌面
process = (
           ffmpeg.output(
               ffmpeg.input(
                   filename='desktop', format='gdigrab', framerate=fps, offset_x=offset_x, offset_y=offset_y,
                   draw_mouse=draw_mouse, s=f'{width}x{height}'),
               filename=filename, pix_fmt='yuv420p'
           ).overwrite_output()
       )
# cmd: ffmpeg路径,如不设置,会搜寻环境变量下的ffmpeg
# 可直接下载ffmpeg.exe到工程文件目录下
ffmpeg_path = 'ffmpeg.exe'
process.run_async(cmd=ffmpeg_path, pipe_stdin=True, pipe_stdout=False, pipe_stderr=False)
# 自定义延时函数
delay()
# 传入中断参数,在调用之前,尽量在之前有足够的延时
process.communicate(str.encode("q"))
process.terminate()

合成音视频

# 传入的视频路径
video_path = 'mp4_test.mp4'
# 传入的音频路径
audio_path = 'mp3_test.mp3'
# 生成的视频名称,不要和上述的路径一致
output_path = 'mixer.mp4'

process = (
           ffmpeg.output(
               ffmpeg.input(filename=video_path),
               ffmpeg.input(filename=audio_path),
               filename=output_path, vcodec='copy', acodec='aac', strict='experimental', pix_fmt='yuv420p'
           ).overwrite_output()

ffmpeg_path = 'ffmpeg.exe'
process.run_async(cmd=ffmpeg_path, pipe_stdin=True, pipe_stdout=False, pipe_stderr=False)

time.sleep(1)
process.communicate(str.encode("q"))
process.terminate()

ps: 上述方法也可以封装到类中,方便pyqt5窗口的实现。

看到这里可能会想到,有音频录制,视频录制,音视频合成,但是不好让音视频分开录制,导致音视频不同步,看起来也别扭,下面就来实现将两者同时录制同时结束。

可沿用录制屏幕制作视频(推荐用本篇下方的代码),录制音频 两篇里的代码,将关于键盘监听部分注释掉,避免冲突。

from threading import Thread
from pynput import keyboard
from Audio_record import AudioRecord
from Screenshot_record import Screenshot

def hotkey():
   """热键监听"""
   with keyboard.Listener(on_press=on_press) as listener:
       listener.join()
def on_press(key):
   try:
       video.terminate()
       if key.char == 't':  # t键,录制结束,保存音视频
           audio.stop_flag = True
       elif key.char == 'k':  # k键,录制中止,删除文件
           audio.kill = True
           video.unlink('test.mp4')
   except Exception as e:
       print(e)
key_thread = Thread(target=hotkey, daemon=True)
audio = AudioRecord()
video = Screenshot()
key_thread.start()
audio.run(filename='test.mp3')
video.record('test.mp4')

利用三组线程,当该代码运行时就会监听键盘按键,同时录制音频、视频,当按下t键结束录制,保存音视频。

"""
Screenshot_record.py 使用ffmpeg录制屏幕
from pathlib import Path
import ffmpeg

class Screenshot:
   def __init__(self, width=1920, height=1080, fps=15):
       self.width = width
       self.height = height
       self.fps = fps
       self.process = None
       self.ffmpeg_path = file_path('ffmpeg.exe')
   def __call__(self, width, height, fps=None):
       self.fps = fps if fps else self.fps
   @staticmethod
   def unlink(filename):
       Path(filename).unlink()
   def record(self, filename, offset_x=0, offset_y=0, draw_mouse=0):
       self.process = (
           ffmpeg.output(
               ffmpeg.input(
                   filename='desktop', format='gdigrab', framerate=self.fps, offset_x=offset_x, offset_y=offset_y,
                   draw_mouse=draw_mouse, s=f'{self.width}x{self.height}'),
               filename=filename, pix_fmt='yuv420p'
           ).overwrite_output()
       )
       self.ffmpeg_async()
   def compose_audio(self, video_path, audio_path, output_path):
               ffmpeg.input(filename=video_path),
               ffmpeg.input(filename=audio_path),
               filename=output_path, vcodec='copy', acodec='aac', strict='experimental', pix_fmt='yuv420p'
   def ffmpeg_async(self):
       self.process = self.process.run_async(cmd=self.ffmpeg_path, pipe_stdin=True, pipe_stdout=False,
                                             pipe_stderr=False)
   def terminate(self):
       if self.process is not None:
           self.process.communicate(str.encode("q"))
           self.process.terminate()
           self.process = None

来源:https://blog.csdn.net/weixin_46281427/article/details/124228056

标签:python,ffmpeg,合成,视频,音频
0
投稿

猜你喜欢

  • 谷歌浏览器Chrome的javascript引擎

    2008-09-04 12:24:00
  • sqlserver中在指定数据库的所有表的所有列中搜索给定的值

    2011-09-30 11:27:38
  • 联动选择菜单(二级联动菜单 三 级联动菜单)

    2023-06-26 22:37:55
  • Python实现绘制多角星实例

    2023-08-26 13:42:14
  • 网页设计技巧:相对路径与绝对路径的区别问题

    2008-03-04 10:12:00
  • Python常见MongoDB数据库操作实例总结

    2023-07-08 08:48:34
  • javascript 获取硬盘信息代码

    2007-12-08 21:27:00
  • Oracle 11g安装错误提示未找到wfmlrsvcapp.ear的解决方法

    2023-07-14 14:31:52
  • 自然描述与自然任务

    2010-01-26 15:51:00
  • MYSQL教程:查询优化之调度和锁定

    2009-02-27 15:58:00
  • 按钮在 IE 中两边被拉伸的 BUG

    2008-11-17 20:37:00
  • 五个常用MySQL图形化管理工具

    2012-01-05 18:49:16
  • Python实现清除文件夹中重复视频

    2023-07-25 16:20:48
  • 仿淘宝星级评分效果

    2010-09-03 18:37:00
  • Python中的类与类型示例详解

    2023-08-12 12:21:42
  • 利用python实现PSO算法优化二元函数

    2022-06-17 20:53:04
  • 2007淘宝UED招聘题解(前端开发部分)

    2007-11-24 10:32:00
  • Python中关于函数的具体用法范例以及介绍

    2023-06-04 19:48:28
  • 隐藏修改文件时间和文件属性的ASP脚本

    2011-03-17 11:15:00
  • PHP导出数据超时的优化建议

    2023-06-29 18:36:32
  • asp之家 网络编程 m.aspxhome.com