【问题标题】:Is there a way to cut frames from a video to reduce its size and duration?有没有办法从视频中剪切帧以减少其大小和持续时间?
【发布时间】:2020-06-19 16:21:44
【问题描述】:

我有大量视频需要处理,但这进展缓慢,因为处理涉及以大约 0.6FPS 的速度运行整个视频,并且绝大多数帧之间几乎没有变化。

有没有什么方法可以让我每两秒对视频进行一次采样并将其保存为另一个视频,将帧速率和持续时间一分为二?我不担心这样做会丢失信息,我很乐意将 10 分钟的视频缩减到几百帧。我确实需要它是一个视频文件,而不是一组图像。

【问题讨论】:

  • 是的,为什么不抽取输入?例如,在 10 帧中,您只选择一个并处理它。只需忽略其余的帧。每次从视频中检索帧时,都会增加一个计数器。当帧计数器达到“抽取值”时,仅处理一个帧。处理完目标帧后清除计数器并重新开始计数。

标签: python opencv video


【解决方案1】:

您可以使用cv2.VideoCapturecv2.VideoWriterFFmpeg 来解决它。

下面的解决方案使用ffmpeg-python
我发布了 OpenCV 解决方案和 FFmpeg 解决方案。

使用 OpenCV 求解:

  • 使用cv2.VideoCapture打开输入视频文件以供阅读。
  • 使用cv2.VideoWriter打开输出视频文件进行写入。
  • 读取所有帧,但仅每 10 帧写入输出文件。

使用 FFmpeg 解决:

以下示例是“自包含”的 - 生成合成输入视频文件进行测试,并对生成的输入视频执行跳帧。

这里是代码(使用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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-04-09
    • 2017-02-15
    • 2011-03-22
    • 2021-09-24
    • 2019-10-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多