Как вывести сжатое видео x265 с помощью cv2.VideoWriter - PullRequest
1 голос
/ 17 апреля 2020

Я выполняю рендеринг на 45-минутном видео 1,2 ГБ, размером 80,0000 кадров, размером 1344x756 каждый, и видео в формате mp4, я пытаюсь вывести видео со сжатием x265, проблема в том, что я Я использую cv2.VideoWriter, выходной размер видео за 10 минут превышает 2 ГБ, что я не собираюсь закончить, поэтому я попробовал следующее на ma c osx и ubuntu 18:

codec = cv2.VideoWriter_fourcc(*'HEVC')
out = cv2.VideoWriter('output.mp4', 'HEVC', fps, (width, height))

Все, что я получаю, - это предупреждения во время выполнения:

OpenCV: FFMPEG: tag 0x43564548/'HEVC' is not found (format 'mp4 / MP4 (MPEG-4 Part 14)')'

То, чего я пытаюсь добиться, - это не обязательно выход наивысшего качества, а хорошее качество и минимально возможный размер.

1 Ответ

1 голос
/ 18 апреля 2020

Насколько я знаю, OpenCV VideoWriter не поддерживает кодирование HEV C (пока).

Я рекомендую вам использовать FFmpeg в качестве подпроцесса и ТРУБОПРОВОДИТЬ визуализированные кадры до stdin входного потока ffmpeg.

Вы можете использовать Python привязку для ffmpeg, например ffmpeg- python, или выполнить ffmpeg, используя Python подпроцесс .

Используя ffmpeg, вы получаете гораздо больший контроль над параметрами кодирования видео по сравнению с cv2.VideoWriter (cv2.VideoWriter разработан для простоты и большей гибкости).

Вот пример кода, который отображает 50 кадров, потоковые кадры в ffmpeg, который кодирует видеофайл MP4 с HEV C видеокодом c:

import cv2
import numpy as np
import subprocess as sp

width, height, n_frames, fps = 1344, 756, 50, 25  # 50 frames, resolution 1344x756, and 25 fps

output_filename = 'output.mp4'

# Open ffmpeg application as sub-process
# FFmpeg input PIPE: RAW images in BGR color format
# FFmpeg output MP4 file encoded with HEVC codec.
# Arguments list:
# -y                   Overwrite output file without asking
# -s {width}x{height}  Input resolution width x height (1344x756)
# -pixel_format bgr24  Input frame color format is BGR with 8 bits per color component
# -f rawvideo          Input format: raw video
# -r {fps}             Frame rate: fps (25fps)
# -i pipe:             ffmpeg input is a PIPE
# -vcodec libx265      Video codec: H.265 (HEVC)
# -pix_fmt yuv420p     Output video color space YUV420 (saving space compared to YUV444)
# -crf 24              Constant quality encoding (lower value for higher quality and larger output file).
# {output_filename}    Output file name: output_filename (output.mp4)
process = sp.Popen(f'ffmpeg -y -s {width}x{height} -pixel_format bgr24 -f rawvideo -r {fps} -i pipe: -vcodec libx265 -pix_fmt yuv420p -crf 24 {output_filename}', stdin=sp.PIPE)

# Build synthetic video frames and write them to ffmpeg input stream.
for i in range(n_frames):
    # Build synthetic image for testing ("render" a video frame).
    img = np.full((height, width, 3), 60, np.uint8)
    cv2.putText(img, str(i+1), (width//2-100*len(str(i+1)), height//2+100), cv2.FONT_HERSHEY_DUPLEX, 10, (255, 30, 30), 20)  # Blue number

    # Write raw video frame to input stream of ffmpeg sub-process.
    process.stdin.write(img.tobytes())

# Close and flush stdin
process.stdin.close()

# Wait for sub-process to finish
process.wait()

# Terminate the sub-process
process.terminate()

Примечание:
ffmpeg исполняемый файл должен находиться в пути выполнения сценария Python.

...