You've already forked FrameTour-RenderWorker
埋点
This commit is contained in:
146
util/ffmpeg.py
146
util/ffmpeg.py
@ -1,3 +1,4 @@
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import subprocess
|
||||
@ -5,60 +6,81 @@ from datetime import datetime
|
||||
from typing import Optional, IO
|
||||
|
||||
from entity.ffmpeg import FfmpegTask, ENCODER_ARGS, PROFILE_LEVEL_ARGS
|
||||
from telemetry import get_tracer
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
def to_annexb(file):
|
||||
if not os.path.exists(file):
|
||||
return file
|
||||
logger.info("ToAnnexb: %s", file)
|
||||
ffmpeg_process = subprocess.run(["ffmpeg", "-y", "-hide_banner", "-i", file, "-c", "copy", "-bsf:v", "h264_mp4toannexb",
|
||||
"-f", "mpegts", file+".ts"])
|
||||
logger.info("ToAnnexb: %s, returned: %s", file, ffmpeg_process.returncode)
|
||||
if ffmpeg_process.returncode == 0:
|
||||
os.remove(file)
|
||||
return file+".ts"
|
||||
else:
|
||||
return file
|
||||
with get_tracer("ffmpeg").start_as_current_span("to_annexb") as span:
|
||||
span.set_attribute("file.path", file)
|
||||
if not os.path.exists(file):
|
||||
return file
|
||||
logger.info("ToAnnexb: %s", file)
|
||||
ffmpeg_process = subprocess.run(["ffmpeg", "-y", "-hide_banner", "-i", file, "-c", "copy", "-bsf:v", "h264_mp4toannexb",
|
||||
"-f", "mpegts", file+".ts"])
|
||||
span.set_attribute("ffmpeg.args", json.dumps(ffmpeg_process.args))
|
||||
logger.info("ToAnnexb: %s, returned: %s", file, ffmpeg_process.returncode)
|
||||
span.set_attribute("ffmpeg.code", ffmpeg_process.returncode)
|
||||
if ffmpeg_process.returncode == 0:
|
||||
span.set_attribute("file.size", os.path.getsize(file+".ts"))
|
||||
os.remove(file)
|
||||
return file+".ts"
|
||||
else:
|
||||
return file
|
||||
|
||||
def re_encode_and_annexb(file):
|
||||
if not os.path.exists(file):
|
||||
return file
|
||||
logger.info("ReEncodeAndAnnexb: %s", file)
|
||||
ffmpeg_process = subprocess.run(["ffmpeg", "-y", "-hide_banner", "-i", file, *PROFILE_LEVEL_ARGS, *ENCODER_ARGS, "-bsf:v", "h264_mp4toannexb",
|
||||
"-f", "mpegts", file +".ts"])
|
||||
logger.info("ReEncodeAndAnnexb: %s, returned: %s", file, ffmpeg_process.returncode)
|
||||
if ffmpeg_process.returncode == 0:
|
||||
os.remove(file)
|
||||
return file+".ts"
|
||||
else:
|
||||
return file
|
||||
with get_tracer("ffmpeg").start_as_current_span("re_encode_and_annexb") as span:
|
||||
span.set_attribute("file.path", file)
|
||||
if not os.path.exists(file):
|
||||
return file
|
||||
logger.info("ReEncodeAndAnnexb: %s", file)
|
||||
ffmpeg_process = subprocess.run(["ffmpeg", "-y", "-hide_banner", "-i", file, *PROFILE_LEVEL_ARGS, *ENCODER_ARGS, "-bsf:v", "h264_mp4toannexb",
|
||||
"-f", "mpegts", file +".ts"])
|
||||
span.set_attribute("ffmpeg.args", json.dumps(ffmpeg_process.args))
|
||||
logger.info("ReEncodeAndAnnexb: %s, returned: %s", file, ffmpeg_process.returncode)
|
||||
span.set_attribute("ffmpeg.code", ffmpeg_process.returncode)
|
||||
if ffmpeg_process.returncode == 0:
|
||||
span.set_attribute("file.size", os.path.getsize(file+".ts"))
|
||||
os.remove(file)
|
||||
return file+".ts"
|
||||
else:
|
||||
return file
|
||||
|
||||
def start_render(ffmpeg_task: FfmpegTask):
|
||||
logger.info(ffmpeg_task)
|
||||
if not ffmpeg_task.need_run():
|
||||
ffmpeg_task.set_output_file(ffmpeg_task.input_file[0])
|
||||
return True
|
||||
ffmpeg_args = ffmpeg_task.get_ffmpeg_args()
|
||||
logger.info(ffmpeg_args)
|
||||
if len(ffmpeg_args) == 0:
|
||||
ffmpeg_task.set_output_file(ffmpeg_task.input_file[0])
|
||||
return True
|
||||
ffmpeg_process = subprocess.run(["ffmpeg", "-progress", "-", "-loglevel", "error", *ffmpeg_args], **subprocess_args(True))
|
||||
logger.info("FINISH TASK, OUTPUT IS %s", handle_ffmpeg_output(ffmpeg_process.stdout))
|
||||
code = ffmpeg_process.returncode
|
||||
if code != 0:
|
||||
logger.error("FFMPEG ERROR: %s", ffmpeg_process.stderr)
|
||||
return False
|
||||
try:
|
||||
out_file_stat = os.stat(ffmpeg_task.output_file)
|
||||
if out_file_stat.st_size < 4096:
|
||||
logger.error("FFMPEG ERROR: OUTPUT FILE IS TOO SMALL")
|
||||
tracer = get_tracer(__name__)
|
||||
with tracer.start_as_current_span("start_render") as span:
|
||||
span.set_attribute("ffmpeg.task", str(ffmpeg_task))
|
||||
logger.info(ffmpeg_task)
|
||||
if not ffmpeg_task.need_run():
|
||||
ffmpeg_task.set_output_file(ffmpeg_task.input_file[0])
|
||||
return True
|
||||
ffmpeg_args = ffmpeg_task.get_ffmpeg_args()
|
||||
logger.info(ffmpeg_args)
|
||||
if len(ffmpeg_args) == 0:
|
||||
ffmpeg_task.set_output_file(ffmpeg_task.input_file[0])
|
||||
return True
|
||||
ffmpeg_process = subprocess.run(["ffmpeg", "-progress", "-", "-loglevel", "error", *ffmpeg_args], **subprocess_args(True))
|
||||
span.set_attribute("ffmpeg.args", json.dumps(ffmpeg_process.args))
|
||||
ffmpeg_final_out = handle_ffmpeg_output(ffmpeg_process.stdout)
|
||||
span.set_attribute("ffmpeg.out", ffmpeg_final_out)
|
||||
logger.info("FINISH TASK, OUTPUT IS %s", ffmpeg_final_out)
|
||||
code = ffmpeg_process.returncode
|
||||
span.set_attribute("ffmpeg.code", code)
|
||||
if code != 0:
|
||||
logger.error("FFMPEG ERROR: %s", ffmpeg_process.stderr)
|
||||
return False
|
||||
except OSError:
|
||||
logger.error("FFMPEG ERROR: OUTPUT FILE NOT FOUND")
|
||||
return False
|
||||
return True
|
||||
span.set_attribute("ffmpeg.out_file", ffmpeg_task.output_file)
|
||||
try:
|
||||
file_size = os.path.getsize(ffmpeg_task.output_file)
|
||||
span.set_attribute("file.size", file_size)
|
||||
if file_size < 4096:
|
||||
logger.error("FFMPEG ERROR: OUTPUT FILE IS TOO SMALL")
|
||||
return False
|
||||
except OSError:
|
||||
span.set_attribute("file.size", 0)
|
||||
logger.error("FFMPEG ERROR: OUTPUT FILE NOT FOUND")
|
||||
return False
|
||||
return True
|
||||
|
||||
def handle_ffmpeg_output(stdout: Optional[bytes]) -> str:
|
||||
out_time = "0:0:0.0"
|
||||
@ -79,27 +101,31 @@ def handle_ffmpeg_output(stdout: Optional[bytes]) -> str:
|
||||
print("[ ]Speed:", out_time, "@", speed)
|
||||
return out_time+"@"+speed
|
||||
|
||||
|
||||
def duration_str_to_float(duration_str: str) -> float:
|
||||
_duration = datetime.strptime(duration_str, "%H:%M:%S.%f") - datetime(1900, 1, 1)
|
||||
return _duration.total_seconds()
|
||||
|
||||
|
||||
def probe_video_info(video_file):
|
||||
# 获取宽度和高度
|
||||
result = subprocess.run(
|
||||
["ffprobe", '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=width,height:format=duration', '-of',
|
||||
'csv=s=x:p=0', video_file],
|
||||
stderr=subprocess.STDOUT,
|
||||
**subprocess_args(True)
|
||||
)
|
||||
if result.returncode != 0:
|
||||
return 0, 0, 0
|
||||
all_result = result.stdout.decode('utf-8').strip()
|
||||
wh, duration = all_result.split('\n')
|
||||
width, height = wh.strip().split('x')
|
||||
|
||||
return int(width), int(height), float(duration)
|
||||
tracer = get_tracer(__name__)
|
||||
with tracer.start_as_current_span("probe_video_info") as span:
|
||||
span.set_attribute("video.file", video_file)
|
||||
# 获取宽度和高度
|
||||
result = subprocess.run(
|
||||
["ffprobe", '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=width,height:format=duration', '-of',
|
||||
'csv=s=x:p=0', video_file],
|
||||
stderr=subprocess.STDOUT,
|
||||
**subprocess_args(True)
|
||||
)
|
||||
span.set_attribute("ffprobe.args", json.dumps(result.args))
|
||||
span.set_attribute("ffprobe.code", result.returncode)
|
||||
if result.returncode != 0:
|
||||
return 0, 0, 0
|
||||
all_result = result.stdout.decode('utf-8').strip()
|
||||
span.set_attribute("ffprobe.out", all_result)
|
||||
wh, duration = all_result.split('\n')
|
||||
width, height = wh.strip().split('x')
|
||||
return int(width), int(height), float(duration)
|
||||
|
||||
|
||||
# Create a set of arguments which make a ``subprocess.Popen`` (and
|
||||
|
Reference in New Issue
Block a user