解决录制音视频不同步问题

问题

使用opencv录制视频,同时使用pyaudio录制音频,存在两个问题

1.视频录制和音频录制没有同时启动,开始时间对不上

2.视频录制时长和视频保存后的时长不一致,会出现视频变慢的现象

解决方法

1.使用event事件,使两个录制同步开始

2.读取音频视频时长,调整视频帧率,把视频时长调整成和音频一样长,再把音频合并到视频中。

源代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import os
import threading
import time
import wave
from datetime import datetime

import cv2
import pyaudio
from moviepy.editor import *

#全局变量,控制录制停止
allowRecord=False
cap=None
#录像
def record_video(event):
global cap
cap=cv2.VideoCapture(0+ cv2.CAP_DSHOW)
writer=cv2.VideoWriter('output.mp4',cv2.VideoWriter_fourcc(*'MJPG'),25,(640,480))
event.set()
global allowRecord
allowRecord=True#录制启动
print('录像开始时间:'+datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
while allowRecord==True:
ret,frame=cap.read()
if ret:
writer.write(frame)
print('录像结束时间:'+datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
allowRecord=False
cap.release()

#录音
def record_audio(event):
global allowRecord
#等待event启动录制音频
p=pyaudio.PyAudio()
global stream
stream=p.open(format=pyaudio.paInt16,channels=1,rate=16000,input=True,frames_per_buffer=1024)
wf = wave.open('output.wav', 'wb')
wf.setnchannels(1)
wf.setsampwidth(p.get_sample_size(pyaudio.paInt16))
wf.setframerate(16000)
event.wait()
#输出时间戳,精确到毫秒
print('录音开始时间:'+datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
while allowRecord==True:
data=stream.read(1024)
wf.writeframes(data)
wf.close()
print('录音结束时间:'+datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'))
stream.stop_stream() # 关闭流
stream.close()
p.terminate()

#合并视频音频
def merge_video_audio(video_path,audio_path):
audioclip = AudioFileClip(audio_path)
videoclip = VideoFileClip(video_path)
videoclip2 = videoclip.set_audio(audioclip)
video = CompositeVideoClip([videoclip2])
filename=datetime.now().strftime('%Y%m%d%H%M%S')
video.write_videofile(filename+'.mp4', codec='mpeg4', bitrate='1000K') # bitrate 设置比特率,比特率越高, 合并的视频越清晰,视频文件也越大
audioclip.close()
videoclip.close()
videoclip2.close()
video.close()
#列出所有进程名,关闭所有包含'ffmpeg'的进程
process_names=os.popen('tasklist').readlines()
for name in process_names:
if 'ffmpeg' in name:
os.system('taskkill /f /im '+name.split()[0])
os.remove(video_path)
os.remove('output.mp4')
os.rename(audio_path, filename+'.wav')
print('音视频合并成功:'+filename+'.mp4')

#停止录制
def stop_record():
global allowRecord
allowRecord=False

def record_video_with_audio():
event=threading.Event()
event.clear()
t1=threading.Thread(target=record_video,args=(event,))
t2=threading.Thread(target=record_audio,args=(event,))
#同步开启录制
t1.start()
t2.start()
while allowRecord==False:#等待录制启动
time.sleep(0.05)
while allowRecord:#等待录制停止
time.sleep(0.05)
continue

#结束线程
t1.join()
t2.join()
video_path='output.mp4'
audio_path='output.wav'
#查看时长
video_time=VideoFileClip(video_path).duration
audio_time=AudioFileClip(audio_path).duration
print('视频时长:'+str(video_time)+' s')
print('音频时长:'+str(audio_time)+' s')
#把视频压缩的和音频一样长
# Load the video
video = cv2.VideoCapture(video_path)
# Get the frame rate
fps = video.get(cv2.CAP_PROP_FPS)
new_fps=video_time/audio_time*fps
print('调整视频帧率为:'+str(new_fps))
# Set the frame rate
video.set(cv2.CAP_PROP_FPS, new_fps)
video_writer = cv2.VideoWriter('output_new.mp4', cv2.VideoWriter_fourcc(*'MJPG'), new_fps, (640, 480))
while True:
# Read the next frame
success, frame = video.read()
if not success:
break
# Write the frame to the output video
video_writer.write(frame)

# Release the video
video.release()
video_writer.release()
t=threading.Thread(target=merge_video_audio,args=('output_new.mp4','output.wav'))
t.start()

t=threading.Thread(target=record_video_with_audio)
t.start()
time.sleep(10)#录制10s
stop_record()

解决录制音视频不同步问题
https://xinhaojin.github.io/2023/03/23/解决录制音视频不同步问题/
作者
xinhaojin
发布于
2023年3月23日
许可协议