我需要处理大量视频,但是处理速度很慢,因为处理涉及以0.6FPS的速度运行整个视频,并且绝大多数帧之间的变化很小。
是否可以通过某种方式每隔两秒钟对视频进行一次采样,然后将其保存为另一个将帧率和时长减少一倍的视频?我不担心这样做会丢失信息,我很乐意将10分钟的视频缩减到几百帧。我确实需要将其作为视频文件,而不是图像集。
答案 0 :(得分:0)
您可以使用cv2.VideoCapture
和cv2.VideoWriter
或使用FFmpeg来解决它。
以下解决方案使用ffmpeg-python。
我同时发布了OpenCV解决方案和FFmpeg解决方案。
使用OpenCV解决:
cv2.VideoCapture
阅读。cv2.VideoWriter
进行写操作。使用FFmpeg解决:
ffmpeg-python
。 以下示例为“自包含”-生成用于测试的合成输入视频文件,并对生成的输入视频执行跳帧。
以下是代码(底部使用ffmpeg-python
的示例):
import ffmpeg # Note: import ffmpeg is not a must, when using OpenCV solution.
import cv2
import sys
out_filename = 'out.mp4'
# Build synthetic video and read binary data into memory (for testing):
#########################################################################
in_filename = 'in.mp4'
width, height = 320, 240
fps = 1 # 1Hz (just for testing)
# Build synthetic video, for testing:
# ffmpeg -y -f lavfi -i testsrc=size=320x240:rate=1 -c:v libx264 -crf 18 -t 50 in.mp4
(
ffmpeg
.input('testsrc=size={}x{}:rate={}'.format(width, height, fps), f='lavfi')
.output(in_filename, vcodec='libx264', crf=18, t=50)
.overwrite_output()
.run()
)
#########################################################################
# Open video file for reading
in_vid = cv2.VideoCapture(in_filename)
#Exit if video not opened.
if not in_vid.isOpened():
print('Cannot open input video file')
sys.exit()
# Read first image (for getting resolution).
ok, frame = in_vid.read()
if not ok:
print('Cannot read video file')
sys.exit()
width, height = frame.shape[1], frame.shape[0]
# Get frame rate of input video.
fps = in_vid.get(cv2.CAP_PROP_FPS)
# Create video writer
# 264 doesn't come by default with the default installation of OpenCV, but I preferred using H.264 (supposed to be better than XVID).
# https://stackoverflow.com/questions/41972503/could-not-open-codec-libopenh264-unspecified-error
# (I had to download openh264-1.8.0-win64.dll)
out_vid = cv2.VideoWriter(out_filename, cv2.VideoWriter_fourcc(*'H264'), fps, (width, height))
frame_counter = 0
while True:
# Write every 10th frame to output video file.
if ((frame_counter % 10) == 0):
out_vid.write(frame)
# Read a new frame
ok, frame = in_vid.read()
if not ok:
break
frame_counter += 1
out_vid.release()
# Selecting one every n frames from a video using FFmpeg:
# https://superuser.com/questions/1274661/selecting-one-every-n-frames-from-a-video-using-ffmpeg
# ffmpeg -y -r 10 -i in.mp4 -vf "select=not(mod(n\,10))" -vsync vfr -vcodec libx264 -crf 18 1_every_10.mp4
out_filename = '1_every_10.mp4'
# Important: set input frame rate to fps*10
(
ffmpeg
.input(in_filename, r=str(fps*10))
.output(out_filename, vf='select=not(mod(n\,10))', vsync='vfr', vcodec='libx264', crf='18')
.overwrite_output()
.run()
)
如果您正在寻找根据指标计算跳过帧的解决方案,也可以尝试FFmpeg decimate filter。