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
猜你喜欢
- 在日常工作编程中存在着各种随机事件,同样在编程中生成随机数字的时候也是一样,随机有多随机呢?在涉及信息安全的情况下,它是最重要的问题之一。每
- 环境:pyecharts库,echarts-countries-pypkg,echarts-china-provinces-pypkg,ec
- 我的 jupyter-bootbook 是在 ubuntu 下安装 anaconda 获得的,下面的命令在 Windows 下大部分可以运行
- 一、前提解决ES5中只有全局作用域和函数作用域,没有块级作用域而带来的不合理的场景。let基本用法用法和var 一样,只是let声明的变量只
- 某天写代码突然县道这个问题,顺势总结一波JavaScript 函数和变量声明的“提前”(hoist)行为简单的说 如果我们使用 匿名函数va
- 初试牛刀假设你希望学习Python这门语言,却苦于找不到一个简短而全面的入门教程。那么本教程将花费十分钟的时间带你走入Python的大门。本
- 本文实例讲述了python生成IP段的方法。分享给大家供大家参考。具体实现方法如下:#!/usr/local/bin/python#-*-
- 最近做的都是前端的项目,很多项目都有回到顶部的需求,下面把我写js代码做个笔录,方便以后查找。发现还可以添加从快到慢的动画效果和随时下拉滚动
- 一、前言1.1 关于描述性统计分析概括地来说,描述性统计分析就是在收集到的数据的基础上,运用制表和分类,图形以及计算概括性数据来描述数据特征
- 前言这篇文章主要给大家总结了关于学习Python的新手们容易犯的几个错误,一共四个易犯错误,下面来看看详细的介绍吧。一、i+=1 不等于++
- 本文实例为大家分享了python如何删除文件中重复字段的具体代码,供大家参考,具体内容如下原文件内容放在list中,新文件内容按行查找,如果
- update()方法添加键 - 值对到字典dict2。此函数不返回任何值。语法以下是update()方法的语法:dict.upd
- 1. 题目编写程序, 4名牌手打牌,计算机随机将52张牌(不含大小鬼)发给4名牌手,在屏幕上显示每位牌手的牌。提示:设计出3个类:Card类
- 本文实例讲述了python3 常见解密加密算法。分享给大家供大家参考,具体如下:一.使用base64Base64编码,64指A-Z、a-z、
- 保存为.py文件后 运行脚本在后面添加进程名称即可 比如:python proinfo.py qq 即可获取QQ的进程信息,注意不区分大小写
- 本文实例讲述了基于wxpython实现的windows GUI程序。分享给大家供大家参考。具体如下:# using a wx.Frame,
- 最近写运维自动化平台,需要用python写很多的小功能模块。这里就分享一个用Python的paramiko来实现功能的一段代码:复制远程服务
- 【原文地址】 Tip/Trick: How to upload a .SQL file to a Hoster and
- CSSer与其他IT职位一样,在找工作的时候,都会面临着面试官提出的问题,或者给出的试卷。一、超链接点击过后hover样式就不出现的问题?被
- 制作文件备份打开原文件 old_f_name = input(“请输入备份的文件路径:”) old_f = open(old_f_name,