我有巨大的视频数据集(约500000 16帧长度剪辑)。其中一些视频产生的信息如下
[mpeg4 @ 0x561b46a44b80] marker does not match f_code
[mpeg4 @ 0x561b480c0740] Error at MB: 4718
[mpeg4 @ 0x561b4811b640] header damaged
我想找出是哪个视频引起了问题。
首先,我尝试了这个https://superuser.com/questions/100288/how-can-i-check-the-integrity-of-a-video-file-avi-mpeg-mp4解决方案,但是错误文件中什么也没有。
我的第二个想法是读取视频的第一个图像,如果它抛出一个错误,将文件名保存到一个文件中。但是,这似乎不是一条错误消息:尽管消息出现在控制台上,但read
与success=True
一起返回。
然后,我尝试将文件名打印到标准错误(警告消息也在其中),将其保存到一个文件中,并进行一些后处理以提取有问题的视频。
import os
from tqdm import tqdm
import sys
folder = '/path/to/videos'
for f in tqdm(os.listdir(folder)):
sys.stderr.write('BEFORE VIDCAP ' + f + '\n')
vidcap = cv2.VideoCapture(os.path.join(folder,f))
sys.stderr.write('BETWEEN VIDCAP AND SUCCESS' + f + '\n')
success, image = vidcap.read()
sys.stderr.write('AFTER SUCCESS ' + f + '\n')
但是,标准错误的输出顺序如下:
AFTER SUCCESS
[mpeg ...]
[mpeg ...]
...
BEFORE VIDCAP
这是没有意义的,它怎么可能发生在这个顺序,一些破碎的视频应该看到之间的前后之间。(如果我试图单独打开它们,下面或前面的那些也不会被破坏。)
我的最后一个想法是为每个视频创建一个文件,使其成为stderr,并检查非空文件。(我知道这是疯狂的低效,但我没有其他的想法。)
for f in os.listdir(folder):
sys.stderr = open(f + '.txt', 'w')
vidcap = cv2.VideoCapture(os.path.join(folder,f))
success, image = vidcap.read()
这也不起作用,所有的错误文件都是空的,尽管消息仍然出现在标准错误上。
因此,我的问题如下:
发布于 2022-02-16 19:13:24
我同意@Christoph,opencv不是合适的工具。你得自己跑一趟。pyav
可能会给你一个更好的控制,但下面是我对ffmpeg所做的。
运行ffmpeg (使用subprocess.run
)将文件解码为stdout,并将stdout映射到空管道。同时,设置stderr (text)管道,以便捕获所有日志消息。您可以检查returncode
输出的subprocess.run
。如果是非零,则该视频有一个关键错误,无法读取整个文件。如果为零,则可以扫描stderr
str以查找上述错误消息。不幸的是,您需要事先知道所有的错误,因为会有很多[mpeg4 ...
行。
这是我所能想到的最有效的解决方案。
。
取决于opencv
如何使用ffmpeg。它可以捕获所有ffmpeg日志消息,并仅在您完成该文件时显示它们。
如果不是标准错误(第二个代码示例),
这与上述两个答案有关。opencv
将ffmpeg称为子进程,并可能捕获ffmpeg子进程的stderr
。
如果您不想学习如何运行ffmpeg
,可以尝试我的ffmpegio
库(pip install ffmpegio-core
,如果您已经在使用NumPy,也可以使用pip install ffmpegio
),并尝试以下代码:
import ffmpegio
import os
out = ffmpegio.ffmpegprocess.run(
{"inputs": [(filename, None)],
"outputs": [(os.devnull, {"f": "rawvideo"})]},
overwrite=True,
capture_log=True,
)
print(out.returncode)
print(out.stderr)
请注意,会有一个很长的暂停,直到它完成读取文件。如果您想查看进度,可以使用progress
选项。
如果你需要更具体的帮助,请发表评论
发布于 2022-09-16 06:49:43
这是我试过的解决办法。
import av
from rich.progress import track
for vid in track(df.video_id):
try:
with av.open(vid) as container:
stream = container.streams.video[0]
average_fps = int(stream.average_rate)
except:
print(vid)
os.remove(vid)
https://stackoverflow.com/questions/71138431
复制相似问题