python录制音频和视频(opencv、pyaudio);解决opencv录制的视频播放速度快的问题

该文章介绍了一种使用Python的PyAudio和OpenCV库录制视频和音频,然后通过ffmpeg工具进行合并的方法。在处理过程中,作者发现了帧率不匹配导致的播放速度过快和音画不同步问题,通过计算新的帧率解决了此问题,实现了音视频的正确同步。
摘要由CSDN通过智能技术生成

录制视频和音频并合并

import pyaudio
import cv2
import subprocess
import wave
from platform import release

# Set up PyAudio
p = pyaudio.PyAudio()

# Set up OpenCV
cap = cv2.VideoCapture(0)

# 音频采样率
sample_rate = 16000
# fps
frame_rate = 15.625

# 打开pyaudio流录制音频
audio_stream = p.open(format=pyaudio.paInt16,
                      channels=1,
                      rate=sample_rate,
                      frames_per_buffer=1024,
                      input=True)

# 设置视频的FourCC代码和帧大小
fourcc = cv2.VideoWriter_fourcc(*'XVID')
frame_size = (640, 480)

# 创建一个VideoWriter对象来保存视频
video_writer = cv2.VideoWriter('b.mp4', fourcc, frame_rate, frame_size)

audio_data = []
# 开始循环录制
while True:
    # 显示摄像头
    ret, frame = cap.read()
    if ret:
         # 将视频帧保存到视频文件
        video_writer.write(frame)
        cv2.imshow('Camera', frame)
    
        # 从麦克风读取音频数据并将其附加到audio_data变量
        audio = audio_stream.read(1024)
        audio_data.append(audio)
        # 如果用户按下'q'键,则打破循环
        if cv2.waitKey(1) & 0xFF == ord('q'):
            cap.release()
            # 释放摄像头资源
            video_writer.release()
            # 关闭录像窗口
            cv2.destroyAllWindows()

            # 释放音频资源
            audio_stream.stop_stream()
            audio_stream.close()
            p.terminate()
            break
    else:
        break



# 保存音频文件为wav
wf = wave.open('a.wav', 'wb')
wf.setnchannels(1)
wf.setsampwidth(p.get_sample_size(pyaudio.paInt16))
wf.setframerate(16000)
wf.writeframes(b''.join(audio_data))
wf.close()


# 合并音频和视频文件
subprocess.run(["ffmpeg", "-i", "b.mp4", "-i", "a.wav", "-c:v", "copy", "-c:a", "aac", "-strict", "experimental", "output.mp4"])

这里需要注意,录制生成的a.wavb.mp4和最终的output.mp4生成之后,下次运行代码之前要将它们删掉,不然程序一直会处在运行状态。(当然可以在文件名不覆盖的情况下不删除)

opencv录制视频播放速度过快(帧率)

参考👉opencv录屏
虽然这一篇写的是录屏,但博主说的调整帧率的方法还是挺好使的。

new_fps = old_fps * (int(Count) / old_fps) / screen_time

我首先使用录制代码录制了一份frame_rate = 24的视频,播放起来速度还是很快,而且合并上音频音画并不同步。

获取视频文件帧率、帧数和持续时间

采取上面链接博主的方法,我首先获取frame_rate = 24的视频的帧率和帧数

import cv2

# Open the video file
video = cv2.VideoCapture("b.mp4")

# Get the frame rate and number of frames
frame_rate = video.get(cv2.CAP_PROP_FPS)
frame_count = video.get(cv2.CAP_PROP_FRAME_COUNT)

# Calculate the duration of the video
duration = frame_count / frame_rate

# Print the frame rate, number of frames, and duration
print("Frame rate:", frame_rate)
print("Number of frames:", frame_count)
print("Duration:", duration)

# Release the video file
video.release()

输出:

Frame rate: 24.0
Number of frames: 80.0
Duration: 3.3333333333333335

因为音频录制的时间没有什么问题,速度也没啥问题,所以我采用音频的持续时间作为整段视频原本应该持续的时间

获取音频文件持续时间

# 获取音频时长
def audio_duration(audio_file):
    import wave
    with wave.open(audio_file, 'rb') as wav_file:
        num_frames = wav_file.getnframes()
        frame_rate = wav_file.getframerate()
        duration = num_frames / frame_rate
        return duration
audio_duration('a.wav')

输出:

5.12

在看之前博主给出的公式 new_fps = old_fps * (int(Count) / old_fps) / screen_time
那么我这里就是new_fps = 24*(80/24)/5.12=15.625

所以,我将录制的代码中frame_rate改为了15.625,最终合成的视频发现音像是同步的。单独生成的音频和视频也会做后续的分析。如果不需要,可以不留着这两个文件,remove即可。

我的邮箱:k1933211129@163.com,CSDN私信很少看,欢迎各位大佬不吝赐教~

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值