实际问题:
目前 opencv 用于将视频帧写入单个文件。您可以直接附加音频还是有其他方法可以创建小的视频片段,这些片段可以通过 rtp 协议广播或直接从 python 代码广播?
out = cv2.VideoWriter(
'temp/result.avi',
cv2.VideoWriter_fourcc(*'DIVX'),
fps,
(frame_w, frame_h))
... #some frame manipulation happening
out.write(f) # f = video frame
我不想编写视频文件,然后使用 ffmpeg 将其与音频结合起来。
背景:
我正在尝试编写一个需要实时 LypSincing 的应用程序。为此,我正在试验Wave2Lip。起初,这个库似乎很慢,但实际上通过一些优化可以很快。
实验:
我首先使用以下命令手动将一个视频与另一个视频文件进行 lypsinced。
python inference.py --checkpoint_path ptmodels\wav2lip.pth --face testdata\face.mp4 --audio testdata\audio.mp4
face.mp4文件时长25秒,30fps,分辨率854*480 audio.mp4文件时长260秒,30fps,分辨率480x360
总生成时间正好是109秒。在剖析代码并对其进行分析后,我发现有两个部分花费的时间最长:
- 人脸检测部分耗时 48.64 秒
- lypsincing 部分耗时 48.50 秒
然后我用静态图像而不是视频进行了尝试,这大大缩短了时间(在我的用例中,我稍后将只使用同一张脸,因此我将适当地在启动时预先计算人脸检测)。
python inference.py --checkpoint_path ptmodels\wav2lip.pth --face testdata\face.jpg --audio testdata\audio.mp4
- 人脸检测部分耗时 1.01 秒
- lypsincing 部分耗时 48.50 秒
在查看了 lypsincing 部分后,我发现生成了整个 lypsincing 视频,然后与视频相结合
for i, (img_batch, mel_batch, frames, coords) in enumerate(tqdm(gen,
total=int(np.ceil(float(len(mel_chunks))/batch_size)))):
if i == 0:
model = load_model(args.checkpoint_path)
print ("Model loaded")
frame_h, frame_w = full_frames[0].shape[:-1]
out = cv2.VideoWriter('temp/result.avi',
cv2.VideoWriter_fourcc(*'DIVX'), fps, (frame_w, frame_h))
img_batch = torch.FloatTensor(np.transpose(img_batch, (0, 3, 1, 2))).to(device)
mel_batch = torch.FloatTensor(np.transpose(mel_batch, (0, 3, 1, 2))).to(device)
with torch.no_grad():
pred = model(mel_batch, img_batch)
pred = pred.cpu().numpy().transpose(0, 2, 3, 1) * 255.
for p, f, c in zip(pred, frames, coords):
y1, y2, x1, x2 = c
p = cv2.resize(p.astype(np.uint8), (x2 - x1, y2 - y1))
f[y1:y2, x1:x2] = p
out.write(f)
out.release()
command = 'ffmpeg -y -i {} -i {} -strict -2 -q:v 1 {}'.format(args.audio, 'temp/result.avi', args.outfile)
subprocess.call(command, shell=platform.system() != 'Windows')
然后我决定用以下结果分析每个 lypsincing 周期:
lypsinc frames generated for batch 0 containing 128 frames with 30.0fps (video part length: 4.26s), took: 3.51s
lypsinc frames generated for batch 1 containing 128 frames with 30.0fps (video part length: 4.26s), took: 0.73s
lypsinc frames generated for batch 2 containing 128 frames with 30.0fps (video part length: 4.26s), took: 0.76s
...
lypsinc frames generated for batch 53 containing 128 frames with 30.0fps (video part length: 4.26s), took: 0.73s
lypsinc frames generated for batch 54 containing 17 frames with 30.0fps (video part length: 0.56s), took: 0.89s
all lypsinc frames generated, took: 48.50s
结论:在解决了面部检测(或者更像是暂停)后,在第一批视频帧准备好之前,lypsincing 大约需要 5 秒。每个 lypsinced 视频批次长 4.26 秒,计算它大约需要 0.8 秒。这意味着如果要将此视频批次与音频帧一起流式传输,则应该有可能在 5 秒延迟后开始渲染,而不是在此用例中的 50 秒。