From e6a0435b97b060114b43c2b7204e9c9784146d52 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Sun, 3 Jul 2022 13:00:38 +0800 Subject: [PATCH] HEVC --- config.py | 6 +++- templates/index.html | 5 +++ workflow/video.py | 78 ++++++++++++++++++++++++++++++++++++++------ 3 files changed, 78 insertions(+), 11 deletions(-) diff --git a/config.py b/config.py index e3bbea5..7ef00d3 100644 --- a/config.py +++ b/config.py @@ -14,6 +14,8 @@ VIDEO_RESOLUTION = "1280x720" # [ffmpeg] # exec FFMPEG_EXEC = "ffmpeg" +# hevc +FFMPEG_USE_HEVC = False # nvidia_gpu FFMPEG_USE_NVIDIA_GPU = False # intel_gpu @@ -63,8 +65,9 @@ def load_config(): VIDEO_CLIP_OVERFLOW_SEC = section.getfloat('overflow_sec', VIDEO_CLIP_OVERFLOW_SEC) if config.has_section("ffmpeg"): section = config['ffmpeg'] - global FFMPEG_EXEC, FFMPEG_USE_NVIDIA_GPU, FFMPEG_USE_INTEL_GPU, VIDEO_BITRATE, VIDEO_CRF + global FFMPEG_EXEC, FFMPEG_USE_HEVC, FFMPEG_USE_NVIDIA_GPU, FFMPEG_USE_INTEL_GPU, VIDEO_BITRATE, VIDEO_CRF FFMPEG_EXEC = section.get('exec', FFMPEG_EXEC) + FFMPEG_USE_HEVC = section.getboolean('hevc', FFMPEG_USE_HEVC) FFMPEG_USE_NVIDIA_GPU = section.getboolean('nvidia_gpu', FFMPEG_USE_NVIDIA_GPU) FFMPEG_USE_INTEL_GPU = section.getboolean('intel_gpu', FFMPEG_USE_INTEL_GPU) VIDEO_BITRATE = section.get('bitrate', VIDEO_BITRATE) @@ -95,6 +98,7 @@ def get_config(): }, 'ffmpeg': { 'exec': FFMPEG_EXEC, + 'hevc': FFMPEG_USE_HEVC, 'nvidia_gpu': FFMPEG_USE_NVIDIA_GPU, 'intel_gpu': FFMPEG_USE_INTEL_GPU, 'bitrate': VIDEO_BITRATE, diff --git a/templates/index.html b/templates/index.html index c7121bf..ba3b8c9 100644 --- a/templates/index.html +++ b/templates/index.html @@ -63,6 +63,10 @@ 命令 {{ config.ffmpeg.exec }} + + HEVC + + 嘤伟达GPU @@ -225,6 +229,7 @@ }, ffmpeg: { exec: "", + hevc: false, nvidia_gpu: false, intel_gpu: false, bitrate: "", diff --git a/workflow/video.py b/workflow/video.py index a194198..6946256 100644 --- a/workflow/video.py +++ b/workflow/video.py @@ -1,12 +1,20 @@ import os import subprocess +import logging from datetime import datetime, timedelta from typing import IO -from config import FFMPEG_EXEC, VIDEO_BITRATE, FFMPEG_USE_NVIDIA_GPU, VIDEO_CLIP_EACH_SEC, VIDEO_CLIP_OVERFLOW_SEC, \ +from config import FFMPEG_EXEC, FFMPEG_USE_HEVC, VIDEO_BITRATE, FFMPEG_USE_NVIDIA_GPU, VIDEO_CLIP_EACH_SEC, VIDEO_CLIP_OVERFLOW_SEC, \ FFMPEG_USE_INTEL_GPU, VIDEO_OUTPUT_DIR, VIDEO_CRF +LOGGER = logging.getLogger("VIDEO") +ch = logging.StreamHandler() +ch.setLevel(logging.DEBUG) +LOGGER.setLevel(logging.DEBUG) +LOGGER.addHandler(ch) + + def base_ts_to_filename(start_ts: float, is_mp4=False) -> str: base_start = datetime.fromtimestamp(start_ts) if is_mp4: @@ -25,12 +33,20 @@ def get_video_real_duration(filename): def encode_video_with_subtitles(orig_filename: str, subtitles: list[str], base_ts: float): new_filename = base_ts_to_filename(base_ts, False) new_fullpath = os.path.join(VIDEO_OUTPUT_DIR, new_filename) - if FFMPEG_USE_NVIDIA_GPU: - process = get_encode_process_use_nvenc(orig_filename, subtitles, new_fullpath) - elif FFMPEG_USE_INTEL_GPU: - process = get_encode_process_use_intel(orig_filename, subtitles, new_fullpath) + if FFMPEG_USE_HEVC: + if FFMPEG_USE_NVIDIA_GPU: + process = get_encode_hevc_process_use_nvenc(orig_filename, subtitles, new_fullpath) + elif FFMPEG_USE_INTEL_GPU: + process = get_encode_hevc_process_use_intel(orig_filename, subtitles, new_fullpath) + else: + process = get_encode_hevc_process_use_cpu(orig_filename, subtitles, new_fullpath) else: - process = get_encode_process_use_cpu(orig_filename, subtitles, new_fullpath) + if FFMPEG_USE_NVIDIA_GPU: + process = get_encode_process_use_nvenc(orig_filename, subtitles, new_fullpath) + elif FFMPEG_USE_INTEL_GPU: + process = get_encode_process_use_intel(orig_filename, subtitles, new_fullpath) + else: + process = get_encode_process_use_cpu(orig_filename, subtitles, new_fullpath) handle_ffmpeg_output(process.stdout) process.wait() return [new_fullpath] @@ -78,6 +94,48 @@ def get_encode_process_use_cpu(orig_filename: str, subtitles: list[str], new_fil return encode_process +def get_encode_hevc_process_use_nvenc(orig_filename: str, subtitles: list[str], new_filename: str): + print("[+]Use Nvidia NvEnc Acceleration") + encode_process = subprocess.Popen([ + FFMPEG_EXEC, *_common_ffmpeg_setting(), + "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles) + ",hwupload_cuda", + "-c:v", "hevc_nvenc", + *_common_ffmpeg_params(), + # "-t", "10", + new_filename + ], stdout=subprocess.PIPE) + return encode_process + + +def get_encode_hevc_process_use_intel(orig_filename: str, subtitles: list[str], new_filename: str): + print("[+]Use Intel QSV Acceleration") + encode_process = subprocess.Popen([ + FFMPEG_EXEC, *_common_ffmpeg_setting(), + "-hwaccel", "qsv", "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles), + "-c:v", "hevc_qsv", + *_common_ffmpeg_params(), + # "-t", "10", + new_filename + ], stdout=subprocess.PIPE) + return encode_process + + +def get_encode_hevc_process_use_cpu(orig_filename: str, subtitles: list[str], new_filename: str): + print("[+]Use CPU Encode") + encode_process = subprocess.Popen([ + FFMPEG_EXEC, *_common_ffmpeg_setting(), + "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles), + "-c:v", "hevc", + *_common_ffmpeg_params(), + # "-t", "10", + new_filename + ], stdout=subprocess.PIPE) + return encode_process + + def handle_ffmpeg_output(stdout: IO[bytes]) -> str: out_time = "0:0:0.0" speed = "0" @@ -97,9 +155,9 @@ def handle_ffmpeg_output(stdout: IO[bytes]) -> str: if line.startswith(b"speed="): speed = line.replace(b"speed=", b"").decode().strip() _i += 1 - if _i % 600 == 500: - print("[>]Speed:", out_time, "@", speed) - print("[ ]Speed:", out_time, "@", speed) + if _i % 300 == 150: + LOGGER.debug("[>]Speed:{}@{}".format(out_time, speed)) + LOGGER.debug("[ ]Speed:{}@{}".format(out_time, speed)) return out_time @@ -147,6 +205,6 @@ def _common_ffmpeg_params(): return ( "-f", "mp4", "-b:v", VIDEO_BITRATE, "-c:a", "copy", "-preset:v", "fast", "-profile:v", "main", "-avoid_negative_ts", "1", - "-qmin", "18", "-qmax", "38", "-crf", str(VIDEO_CRF), "-g:v", "240", + "-qmin", "18", "-qmax", "38", "-crf", str(VIDEO_CRF), "-g:v", "900", "-fflags", "+genpts", "-shortest" )