From 66e88f0c5516cd9971e1532ef3b0147d98e21243 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Tue, 26 Apr 2022 17:48:23 +0800 Subject: [PATCH] =?UTF-8?q?=E5=8F=8CGPU=E6=94=AF=E6=8C=81=EF=BC=88BETA?= =?UTF-8?q?=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- workflow/video.py | 116 ++++++++++++++++++++++++++++++++++++++++----- workflow/worker.py | 14 +++--- 2 files changed, 110 insertions(+), 20 deletions(-) diff --git a/workflow/video.py b/workflow/video.py index 8739b0d..a7c6147 100644 --- a/workflow/video.py +++ b/workflow/video.py @@ -1,4 +1,5 @@ import os +import platform import subprocess from datetime import datetime, timedelta from typing import IO @@ -7,6 +8,14 @@ from config import FFMPEG_EXEC, VIDEO_BITRATE, FFMPEG_USE_NVIDIA_GPU, VIDEO_CLIP PROD_ENV, FFMPEG_USE_INTEL_GPU +def base_ts_to_filename(start_ts: float, is_mp4=False) -> str: + base_start = datetime.fromtimestamp(start_ts) + if is_mp4: + return base_start.strftime("%Y%m%d_%H%M.mp4") + else: + return base_start.strftime("%Y%m%d_%H%M.flv") + + def get_video_real_duration(filename): ffmpeg_process = subprocess.Popen([ FFMPEG_EXEC, "-hide_banner", "-progress", "-", "-v", "0", "-i", filename, "-c", "copy", "-f", "null", "-" @@ -14,6 +23,75 @@ def get_video_real_duration(filename): return handle_ffmpeg_output(ffmpeg_process.stdout) +def multi_gpu_encode_video_with_subtitles(orig_filename: str, subtitles: list[str], base_ts: float): + new_filename = base_ts_to_filename(base_ts) + if not (FFMPEG_USE_NVIDIA_GPU and FFMPEG_USE_INTEL_GPU): + print("[!]Please Enable Both Of Encode Acceleration") + print("[!]Fallback to normal") + return encode_video_with_subtitles(orig_filename, subtitles, new_filename) + _duration_str = get_video_real_duration(orig_filename) + duration = duration_str_to_float(_duration_str) + if duration >= (VIDEO_CLIP_EACH_SEC * 5): + # qsv 压制前2段,剩余交由nvenc压制 + new_filename0 = base_ts_to_filename(base_ts) + new_filename1 = base_ts_to_filename(base_ts + VIDEO_CLIP_EACH_SEC * 2) + encode_process0 = subprocess.Popen([ + FFMPEG_EXEC, "-hide_banner", "-progress", "-", "-v", "0", "-y", + "-hwaccel", "qsv", "-t", str(VIDEO_CLIP_EACH_SEC * 2 + VIDEO_CLIP_OVERFLOW_SEC), "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles), + "-c:a", "copy", "-c:v", "h264_qsv", + "-f", "mp4", "-preset:v", "fast", "-profile:v", "high", "-level", "4.1", + "-b:v", VIDEO_BITRATE, "-rc:v", "vbr", "-tune:v", "hq", + "-qmin", "10", "-qmax", "32", "-crf", "16", + # "-t", "10", + new_filename0 + ], stdout=subprocess.PIPE) + encode_process1 = subprocess.Popen([ + FFMPEG_EXEC, "-hide_banner", "-progress", "-", "-v", "0", "-y", + "-hwaccel", "cuvid", "-ss", str(VIDEO_CLIP_EACH_SEC * 2), "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles) + ",hwupload_cuda", + "-c:a", "copy", "-c:v", "h264_nvenc", + "-f", "mp4", "-preset:v", "fast", "-profile:v", "high", "-level", "4.1", + "-b:v", VIDEO_BITRATE, "-rc:v", "vbr", "-tune:v", "hq", + "-qmin", "10", "-qmax", "32", "-crf", "16", + # "-t", "10", + new_filename1 + ], stdout=subprocess.PIPE) + return [new_filename0, new_filename1] + elif duration >= (VIDEO_CLIP_EACH_SEC * 3): + # 至少也要能切3片,才用双GPU加速 + new_filename0 = base_ts_to_filename(base_ts, True) + new_filename1 = base_ts_to_filename(base_ts + VIDEO_CLIP_EACH_SEC) + encode_process0 = subprocess.Popen([ + FFMPEG_EXEC, "-hide_banner", "-progress", "-", "-v", "0", "-y", + "-hwaccel", "qsv", "-t", str(VIDEO_CLIP_EACH_SEC + VIDEO_CLIP_OVERFLOW_SEC), "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles), + "-c:a", "copy", "-c:v", "h264_qsv", + "-f", "mp4", "-preset:v", "fast", "-profile:v", "high", "-level", "4.1", + "-b:v", VIDEO_BITRATE, "-rc:v", "vbr", "-tune:v", "hq", + "-qmin", "10", "-qmax", "32", "-crf", "16", + # "-t", "10", + new_filename0 + ], stdout=subprocess.PIPE) + encode_process1 = subprocess.Popen([ + FFMPEG_EXEC, "-hide_banner", "-progress", "-", "-v", "0", "-y", + "-hwaccel", "cuvid", "-ss", str(VIDEO_CLIP_EACH_SEC), "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles) + ",hwupload_cuda", + "-c:a", "copy", "-c:v", "h264_nvenc", + "-f", "mp4", "-preset:v", "fast", "-profile:v", "high", "-level", "4.1", + "-b:v", VIDEO_BITRATE, "-rc:v", "vbr", "-tune:v", "hq", + "-qmin", "10", "-qmax", "32", "-crf", "16", + # "-t", "10", + new_filename1 + ], stdout=subprocess.PIPE) + return [new_filename1] + else: + print("[-]VideoClip to short,", duration) + print("[-]Fallback to normal") + encode_video_with_subtitles(orig_filename, subtitles, new_filename) + return [new_filename] + + def encode_video_with_subtitles(orig_filename: str, subtitles: list[str], new_filename: str): if FFMPEG_USE_NVIDIA_GPU: print("[+]Use Nvidia NvEnc Acceleration") @@ -29,18 +107,32 @@ def encode_video_with_subtitles(orig_filename: str, subtitles: list[str], new_fi new_filename ], stdout=subprocess.PIPE) elif FFMPEG_USE_INTEL_GPU: - print("[+]Use Intel VAAPI Acceleration") - encode_process = subprocess.Popen([ - FFMPEG_EXEC, "-hide_banner", "-progress", "-", "-v", "0", "-y", - "-hwaccel", "vaapi", "-i", orig_filename, "-vf", - ",".join("subtitles=%s" % i for i in subtitles) + ",hwupload", - "-c:a", "copy", "-c:v", "h264_vaapi", - "-f", "mp4", "-preset:v", "fast", "-profile:v", "high", "-level", "4.1", - "-b:v", VIDEO_BITRATE, "-rc:v", "vbr", "-tune:v", "hq", - "-qmin", "10", "-qmax", "32", "-crf", "16", - # "-t", "10", - new_filename - ], stdout=subprocess.PIPE) + if platform.system().lower() == "windows": + print("[+]Use Intel QSV Acceleration") + encode_process = subprocess.Popen([ + FFMPEG_EXEC, "-hide_banner", "-progress", "-", "-v", "0", "-y", + "-hwaccel", "qsv", "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles), + "-c:a", "copy", "-c:v", "h264_qsv", + "-f", "mp4", "-preset:v", "fast", "-profile:v", "high", "-level", "4.1", + "-b:v", VIDEO_BITRATE, "-rc:v", "vbr", "-tune:v", "hq", + "-qmin", "10", "-qmax", "32", "-crf", "16", + # "-t", "10", + new_filename + ], stdout=subprocess.PIPE) + else: + print("[+]Use Intel VAAPI Acceleration") + encode_process = subprocess.Popen([ + FFMPEG_EXEC, "-hide_banner", "-progress", "-", "-v", "0", "-y", + "-hwaccel", "vaapi", "-i", orig_filename, "-vf", + ",".join("subtitles=%s" % i for i in subtitles) + ",hwupload", + "-c:a", "copy", "-c:v", "h264_vaapi", + "-f", "mp4", "-preset:v", "fast", "-profile:v", "high", "-level", "4.1", + "-b:v", VIDEO_BITRATE, "-rc:v", "vbr", "-tune:v", "hq", + "-qmin", "10", "-qmax", "32", "-crf", "16", + # "-t", "10", + new_filename + ], stdout=subprocess.PIPE) else: print("[+]Use CPU Encode") encode_process = subprocess.Popen([ diff --git a/workflow/worker.py b/workflow/worker.py index 9cf8a07..8036532 100644 --- a/workflow/worker.py +++ b/workflow/worker.py @@ -1,9 +1,8 @@ import os.path -from datetime import datetime from exception.danmaku import DanmakuException from workflow.danmaku import get_file_start, diff_danmaku_files, danmaku_to_subtitle -from workflow.video import encode_video_with_subtitles, quick_split_video +from workflow.video import multi_gpu_encode_video_with_subtitles, quick_split_video def do_workflow(video_file, danmaku_base_file, *danmaku_files): @@ -11,8 +10,6 @@ def do_workflow(video_file, danmaku_base_file, *danmaku_files): ... result = [] start_ts = get_file_start(danmaku_base_file) - base_start = datetime.fromtimestamp(start_ts) - new_file_name = base_start.strftime("%Y%m%d_%H%M.flv") result.append(danmaku_to_subtitle(danmaku_base_file, 0)) for danmaku_file in danmaku_files: try: @@ -24,10 +21,11 @@ def do_workflow(video_file, danmaku_base_file, *danmaku_files): print("弹幕文件", danmaku_file, "异常") continue print(result) - encode_video_with_subtitles(video_file, result, new_file_name) - quick_split_video(new_file_name) - # clean files + file_need_split = multi_gpu_encode_video_with_subtitles(video_file, result, start_ts) + for filename in file_need_split: + quick_split_video(filename) + # clean files + os.remove(filename) for file in result: os.remove(file) - os.remove(new_file_name)