This commit is contained in:
Jerry Yan 2022-07-03 13:00:38 +08:00
parent 5535ef9828
commit e6a0435b97
3 changed files with 78 additions and 11 deletions

View File

@ -14,6 +14,8 @@ VIDEO_RESOLUTION = "1280x720"
# [ffmpeg] # [ffmpeg]
# exec # exec
FFMPEG_EXEC = "ffmpeg" FFMPEG_EXEC = "ffmpeg"
# hevc
FFMPEG_USE_HEVC = False
# nvidia_gpu # nvidia_gpu
FFMPEG_USE_NVIDIA_GPU = False FFMPEG_USE_NVIDIA_GPU = False
# intel_gpu # intel_gpu
@ -63,8 +65,9 @@ def load_config():
VIDEO_CLIP_OVERFLOW_SEC = section.getfloat('overflow_sec', VIDEO_CLIP_OVERFLOW_SEC) VIDEO_CLIP_OVERFLOW_SEC = section.getfloat('overflow_sec', VIDEO_CLIP_OVERFLOW_SEC)
if config.has_section("ffmpeg"): if config.has_section("ffmpeg"):
section = config['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_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_NVIDIA_GPU = section.getboolean('nvidia_gpu', FFMPEG_USE_NVIDIA_GPU)
FFMPEG_USE_INTEL_GPU = section.getboolean('intel_gpu', FFMPEG_USE_INTEL_GPU) FFMPEG_USE_INTEL_GPU = section.getboolean('intel_gpu', FFMPEG_USE_INTEL_GPU)
VIDEO_BITRATE = section.get('bitrate', VIDEO_BITRATE) VIDEO_BITRATE = section.get('bitrate', VIDEO_BITRATE)
@ -95,6 +98,7 @@ def get_config():
}, },
'ffmpeg': { 'ffmpeg': {
'exec': FFMPEG_EXEC, 'exec': FFMPEG_EXEC,
'hevc': FFMPEG_USE_HEVC,
'nvidia_gpu': FFMPEG_USE_NVIDIA_GPU, 'nvidia_gpu': FFMPEG_USE_NVIDIA_GPU,
'intel_gpu': FFMPEG_USE_INTEL_GPU, 'intel_gpu': FFMPEG_USE_INTEL_GPU,
'bitrate': VIDEO_BITRATE, 'bitrate': VIDEO_BITRATE,

View File

@ -63,6 +63,10 @@
<td>命令</td> <td>命令</td>
<td>{{ config.ffmpeg.exec }}</td> <td>{{ config.ffmpeg.exec }}</td>
</tr> </tr>
<tr>
<td>HEVC</td>
<td :class="{warning: !config.ffmpeg.hevc, success: config.ffmpeg.hevc}"></td>
</tr>
<tr> <tr>
<td>嘤伟达GPU</td> <td>嘤伟达GPU</td>
<td :class="{warning: !config.ffmpeg.nvidia_gpu, success: config.ffmpeg.nvidia_gpu}"></td> <td :class="{warning: !config.ffmpeg.nvidia_gpu, success: config.ffmpeg.nvidia_gpu}"></td>
@ -225,6 +229,7 @@
}, },
ffmpeg: { ffmpeg: {
exec: "", exec: "",
hevc: false,
nvidia_gpu: false, nvidia_gpu: false,
intel_gpu: false, intel_gpu: false,
bitrate: "", bitrate: "",

View File

@ -1,12 +1,20 @@
import os import os
import subprocess import subprocess
import logging
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import IO 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 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: def base_ts_to_filename(start_ts: float, is_mp4=False) -> str:
base_start = datetime.fromtimestamp(start_ts) base_start = datetime.fromtimestamp(start_ts)
if is_mp4: 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): def encode_video_with_subtitles(orig_filename: str, subtitles: list[str], base_ts: float):
new_filename = base_ts_to_filename(base_ts, False) new_filename = base_ts_to_filename(base_ts, False)
new_fullpath = os.path.join(VIDEO_OUTPUT_DIR, new_filename) new_fullpath = os.path.join(VIDEO_OUTPUT_DIR, new_filename)
if FFMPEG_USE_NVIDIA_GPU: if FFMPEG_USE_HEVC:
process = get_encode_process_use_nvenc(orig_filename, subtitles, new_fullpath) if FFMPEG_USE_NVIDIA_GPU:
elif FFMPEG_USE_INTEL_GPU: process = get_encode_hevc_process_use_nvenc(orig_filename, subtitles, new_fullpath)
process = get_encode_process_use_intel(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: 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) handle_ffmpeg_output(process.stdout)
process.wait() process.wait()
return [new_fullpath] return [new_fullpath]
@ -78,6 +94,48 @@ def get_encode_process_use_cpu(orig_filename: str, subtitles: list[str], new_fil
return encode_process 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: def handle_ffmpeg_output(stdout: IO[bytes]) -> str:
out_time = "0:0:0.0" out_time = "0:0:0.0"
speed = "0" speed = "0"
@ -97,9 +155,9 @@ def handle_ffmpeg_output(stdout: IO[bytes]) -> str:
if line.startswith(b"speed="): if line.startswith(b"speed="):
speed = line.replace(b"speed=", b"").decode().strip() speed = line.replace(b"speed=", b"").decode().strip()
_i += 1 _i += 1
if _i % 600 == 500: if _i % 300 == 150:
print("[>]Speed:", out_time, "@", speed) LOGGER.debug("[>]Speed:{}@{}".format(out_time, speed))
print("[ ]Speed:", out_time, "@", speed) LOGGER.debug("[ ]Speed:{}@{}".format(out_time, speed))
return out_time return out_time
@ -147,6 +205,6 @@ def _common_ffmpeg_params():
return ( return (
"-f", "mp4", "-b:v", VIDEO_BITRATE, "-c:a", "copy", "-f", "mp4", "-b:v", VIDEO_BITRATE, "-c:a", "copy",
"-preset:v", "fast", "-profile:v", "main", "-avoid_negative_ts", "1", "-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" "-fflags", "+genpts", "-shortest"
) )