From 2afd877937fd63e8cb6cb5a498799f55e7bbe582 Mon Sep 17 00:00:00 2001 From: Jerry Yan <792602257@qq.com> Date: Tue, 6 Sep 2022 07:30:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81hevc=E9=85=8D=E7=BD=AE?= =?UTF-8?q?=E5=88=87=E6=8D=A2=EF=BC=8C=E6=94=AF=E6=8C=81gop=E8=AE=BE?= =?UTF-8?q?=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- config.py | 49 +++++++++++++++++++++++++++---- danmaku_workflow.py | 71 ++++++++++++++++++++++++++++++++++++++------- 2 files changed, 103 insertions(+), 17 deletions(-) diff --git a/config.py b/config.py index 5025d27..035b8ea 100644 --- a/config.py +++ b/config.py @@ -9,22 +9,41 @@ DANMAKU_FACTORY_EXEC = "DanmakuFactory" DANMAKU_SPEED = 12 # font DEFAULT_FONT_NAME = "Sarasa Term SC" +# font_size +DANMAKU_FONT_SIZE = 40 # resolution VIDEO_RESOLUTION = "1280x720" # [ffmpeg] # exec FFMPEG_EXEC = "ffmpeg" +# hevc +FFMPEG_USE_HEVC = False # nvidia_gpu -FFMPEG_USE_NVIDIA_GPU = True +FFMPEG_USE_NVIDIA_GPU = False # intel_gpu -FFMPEG_USE_INTEL_GPU = True +FFMPEG_USE_INTEL_GPU = False # bitrate VIDEO_BITRATE = "2.5M" # crf -VIDEO_CRF = 26 +VIDEO_CRF = 28 +# gop +VIDEO_GOP = 60 # [video] +# enabled +VIDEO_ENABLED = False # title VIDEO_TITLE = "【永恒de草薙直播录播】直播于 {}" +# desc +VIDEO_DESC = "弹幕来源:B站直播\r\n\r\n" + \ + "原主播:永恒de草薙\r\n往期节目单查询:https://comment.sc.jerryyan.top\r\n\r\n" + \ + "好多人这时候就开始问了,在哪直播呀,哎。对吧…咱来啦啊。在哔哩哔哩啊," \ + "无论你是用网页百度搜索哔哩哔哩官网或者是用手机的APP下载一个哔哩哔哩," \ + "啊,都能找到原主播。大概每天晚七点半左右吧…一般都是往左。然后的话呢搜索永恒de草薙就能找到他。" \ + "那么今天的话呢今天的录播也就发完了…他是本期的主播永恒。咱明天同一时间不见不散…拜拜!!" +# tid +VIDEO_TID = 17 +# tags +VIDEO_TAGS = "永恒de草薙,三国,三国战记,直播录像,录播,怀旧,街机" # [clip] # each_sec VIDEO_CLIP_EACH_SEC = 6000 @@ -47,15 +66,20 @@ def load_config(): config.read("config.ini", encoding="utf-8") if config.has_section("danmaku"): section = config['danmaku'] - global DANMAKU_FACTORY_EXEC, DANMAKU_SPEED, DEFAULT_FONT_NAME, VIDEO_RESOLUTION + global DANMAKU_FACTORY_EXEC, DANMAKU_SPEED, DEFAULT_FONT_NAME, VIDEO_RESOLUTION, DANMAKU_FONT_SIZE DANMAKU_FACTORY_EXEC = section.get('exec', DANMAKU_FACTORY_EXEC) DANMAKU_SPEED = section.getfloat('speed', DANMAKU_SPEED) DEFAULT_FONT_NAME = section.get('font', DEFAULT_FONT_NAME) + DANMAKU_FONT_SIZE = section.getint('font_size', DANMAKU_FONT_SIZE) VIDEO_RESOLUTION = section.get('resolution', VIDEO_RESOLUTION) if config.has_section("video"): section = config['video'] - global VIDEO_TITLE + global VIDEO_ENABLED, VIDEO_TITLE, VIDEO_DESC, VIDEO_TID, VIDEO_TAGS + VIDEO_ENABLED = section.getboolean('enabled', VIDEO_ENABLED) VIDEO_TITLE = section.get('title', VIDEO_TITLE) + VIDEO_DESC = section.get('desc', VIDEO_DESC) + VIDEO_TID = section.getint('tid', VIDEO_TID) + VIDEO_TAGS = section.get('tags', VIDEO_TAGS) if config.has_section("clip"): section = config['clip'] global VIDEO_CLIP_EACH_SEC, VIDEO_CLIP_OVERFLOW_SEC @@ -63,12 +87,15 @@ 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, \ + VIDEO_GOP 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) VIDEO_CRF = section.getfloat('crf', VIDEO_CRF) + VIDEO_GOP = section.getfloat('gop', VIDEO_GOP) if config.has_section("recorder"): global BILILIVE_RECORDER_DIRECTORY, XIGUALIVE_RECORDER_DIRECTORY, VIDEO_OUTPUT_DIR section = config['recorder'] @@ -84,18 +111,28 @@ def get_config(): 'exec': DANMAKU_FACTORY_EXEC, 'speed': DANMAKU_SPEED, 'font': DEFAULT_FONT_NAME, + 'font_size': DANMAKU_FONT_SIZE, 'resolution': VIDEO_RESOLUTION, }, + 'video': { + 'enabled': VIDEO_ENABLED, + 'title': VIDEO_TITLE, + 'desc': VIDEO_DESC, + 'tid': VIDEO_TID, + 'tags': VIDEO_TAGS, + }, 'clip': { 'each_sec': VIDEO_CLIP_EACH_SEC, 'overflow_sec': VIDEO_CLIP_OVERFLOW_SEC, }, 'ffmpeg': { 'exec': FFMPEG_EXEC, + 'hevc': FFMPEG_USE_HEVC, 'nvidia_gpu': FFMPEG_USE_NVIDIA_GPU, 'intel_gpu': FFMPEG_USE_INTEL_GPU, 'bitrate': VIDEO_BITRATE, 'crf': VIDEO_CRF, + 'gop': VIDEO_GOP, }, 'recorder': { 'bili_dir': BILILIVE_RECORDER_DIRECTORY, diff --git a/danmaku_workflow.py b/danmaku_workflow.py index 96b53d2..694956a 100644 --- a/danmaku_workflow.py +++ b/danmaku_workflow.py @@ -16,7 +16,7 @@ from PyQt5.QtWidgets import QWidget, QLabel, QApplication, QFrame, QVBoxLayout, from danmaku_xml_helper import get_file_start, diff_danmaku_files, NoDanmakuException from config import load_config, FFMPEG_EXEC, DANMAKU_FACTORY_EXEC, FFMPEG_USE_INTEL_GPU, FFMPEG_USE_NVIDIA_GPU, \ VIDEO_BITRATE, VIDEO_CLIP_EACH_SEC, VIDEO_CLIP_OVERFLOW_SEC, VIDEO_RESOLUTION, DANMAKU_SPEED, DEFAULT_FONT_NAME, \ - VIDEO_OUTPUT_DIR, VIDEO_CRF + VIDEO_OUTPUT_DIR, VIDEO_CRF, VIDEO_GOP, FFMPEG_USE_HEVC class Job: @@ -315,12 +315,20 @@ class WorkerThread(QThread): def encode_video_with_subtitles(self, 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) self.handle_ffmpeg_output(process.stdout) process.wait() return [new_fullpath] @@ -420,7 +428,7 @@ def get_encode_process_use_nvenc(orig_filename: str, subtitles: list[str], new_f encode_process = subprocess.Popen([ FFMPEG_EXEC, *_common_ffmpeg_setting(), "-i", orig_filename, "-vf", - ",".join("subtitles=%s" % i for i in subtitles), + ",".join("subtitles=%s" % i for i in subtitles) + ",hwupload_cuda", "-c:v", "h264_nvenc", *_common_ffmpeg_params(), # "-t", "10", @@ -433,14 +441,13 @@ def get_encode_process_use_intel(orig_filename: str, subtitles: list[str], new_f print("[+]Use Intel QSV Acceleration") encode_process = subprocess.Popen([ FFMPEG_EXEC, *_common_ffmpeg_setting(), - "-init_hw_device", "qsv=hw", "-filter_hw_device", "hw", - "-i", orig_filename, "-vf", + "-hwaccel", "qsv", "-i", orig_filename, "-vf", ",".join("subtitles=%s" % i for i in subtitles), "-c:v", "h264_qsv", *_common_ffmpeg_params(), # "-t", "10", new_filename - ], stdout=subprocess.PIPE) + ], **subprocess_args(True)) return encode_process @@ -458,6 +465,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 + ], **subprocess_args(True)) + 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 + ], **subprocess_args(True)) + 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 + ], **subprocess_args(True)) + return encode_process + + # Create a set of arguments which make a ``subprocess.Popen`` (and # variants) call work with or without Pyinstaller, ``--noconsole`` or # not, on Windows and Linux. Typical use:: @@ -552,7 +601,7 @@ 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", str(VIDEO_GOP), "-fflags", "+genpts", "-shortest", "-movflags", "faststart" )