我在运行程序
extract_frame_and_wav_multiprocess.py
时遇到以下错误,该程序旨在从数据集MSRVTT
中的视频中提取音频和帧。
这是程序的错误消息:
(valor) xxx:/VALOR/utils$ python extract_frame_and_wav_multiprocess.py
0%| | 0/10005 [00:00<?, ?it/s]
Exception in thread Thread-3:
Traceback (most recent call last):
File "/anaconda3/envs/valor/lib/python3.9/threading.py", line 973, in _bootstrap_inner
self.run()
File "/anaconda3/envs/valor/lib/python3.9/threading.py", line 910, in run
self._target(*self._args, **self._kwargs)
File "/anaconda3/envs/valor/lib/python3.9/multiprocessing/pool.py", line 576, in _handle_results
task = get()
File "/anaconda3/envs/valor/lib/python3.9/multiprocessing/connection.py", line 256, in recv
return _ForkingPickler.loads(buf.getbuffer())
TypeError: __init__() missing 2 required positional arguments: 'stdout' and 'stderr'
这是错误消息指示的位置(在文件
/anaconda3/envs/valor/lib/python3.9/multiprocessing/connection.py
中):
def recv(self):
"""Receive a (picklable) object"""
self._check_closed()
self._check_readable()
buf = self._recv_bytes()
return _ForkingPickler.loads(buf.getbuffer())
以下程序是正在执行的python程序
extract_frame_and_wav_multiprocess.py
:
import os
import os.path as P
import ffmpeg
import json
import tqdm
import numpy as np
import threading
import time
import multiprocessing
from multiprocessing import Pool
import subprocess
### change diffenrent datasets
input_path = '../datasets/msrvtt/raw_videos'
output_path = '../datasets/msrvtt/testt'
data_list = os.listdir(input_path)
def execCmd(cmd):
r = os.popen(cmd)
text = r.read()
r.close()
return text
def pipline(video_path, video_probe, output_dir, fps, sr, duration_target):
video_name = os.path.basename(video_path)
audio_name = video_name.replace(".mp4", ".wav")
video_name = video_name.replace(".mp4", "")
#extract video frames fps
fps_frame_dir = P.join(output_dir, f"frames_fps{fps}", video_name)
os.makedirs(fps_frame_dir, exist_ok=True)
cmd = "ffmpeg -loglevel error -i {} -vsync 0 -f image2 -vf fps=fps={:.02f} -qscale:v 2 {}/frame_%04d.jpg".format(
video_path, fps, fps_frame_dir)
subprocess.call(cmd, shell=True)
# Extract Audio
sr_audio_dir = P.join(output_dir,f"audio_{sr}hz")
os.makedirs(sr_audio_dir, exist_ok=True)
audio_file_path = P.join(sr_audio_dir, audio_name)
cmd = "ffmpeg -i {} -loglevel error -f wav -vn -ac 1 -ab 16k -ar {} -y {}".format(
video_path, sr, audio_file_path)
subprocess.call(cmd, shell=True)
def extract_thread(video_id):
video_name = os.path.join(input_path, video_id)
if not os.path.exists(video_name):
return
probe = ffmpeg.probe(video_name)
pipline(video_name, probe, output_path, fps=4, sr=22050, duration_target=10)
def extract_all(video_ids, thread_num, start):
length = len(video_ids)
print(length)
with Pool(thread_num) as p:
list(tqdm.tqdm(p.imap(extract_thread, video_ids), total=length))
if __name__=='__main__':
thread_num = 50
start = 0
print(len(data_list))
extract_all(data_list, thread_num, start)
奇怪的是,在处理
DiDeMo
视频数据集时没有出现类似的错误,但在处理MSRVTT
数据集时却遇到了。 (这与DiDeMo
数据集没有音频有关吗?)
由于Python等依赖的版本兼容性问题,在
subprocess.Popen
模块内调用ffmpeg.probe
时,即使我们输入了stdout、stderr等参数,仍然会抛出stdout缺失等错误。因此,我们省略了使用 ffmpeg.probe
命令记录信息的步骤。 probe = ffmpeg.probe(video_name)
pipline(video_name, probe, output_path, fps=1, sr=22050, duration_target=10)
进入以下代码:
# probe = ffmpeg.probe(video_name)
pipline(video_name, None, output_path, fps=1, sr=22050, duration_target=10)