You've already forked FrameTour-RenderWorker
345 lines
13 KiB
Python
345 lines
13 KiB
Python
import json
|
|
import logging
|
|
import os
|
|
import threading
|
|
import time
|
|
from urllib3.util.retry import Retry
|
|
from requests.adapters import HTTPAdapter
|
|
|
|
import requests
|
|
from opentelemetry.trace import Status, StatusCode
|
|
|
|
import util.system
|
|
from telemetry import get_tracer
|
|
from util import oss
|
|
|
|
# 创建带有连接池和重试策略的会话
|
|
session = requests.Session()
|
|
|
|
# 配置重试策略
|
|
retry_strategy = Retry(
|
|
total=3,
|
|
status_forcelist=[429, 500, 502, 503, 504],
|
|
backoff_factor=1,
|
|
respect_retry_after_header=True,
|
|
)
|
|
|
|
# 配置HTTP适配器(连接池)
|
|
adapter = HTTPAdapter(pool_connections=10, pool_maxsize=20, max_retries=retry_strategy)
|
|
|
|
session.mount("http://", adapter)
|
|
session.mount("https://", adapter)
|
|
|
|
# 设置默认超时
|
|
session.timeout = 30
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def normalize_task(task_info):
|
|
...
|
|
return task_info
|
|
|
|
|
|
def sync_center():
|
|
"""
|
|
通过接口获取任务
|
|
:return: 任务列表
|
|
"""
|
|
from services import DefaultTemplateService
|
|
|
|
template_service = DefaultTemplateService()
|
|
try:
|
|
response = session.post(
|
|
os.getenv("API_ENDPOINT") + "/sync",
|
|
json={
|
|
"accessKey": os.getenv("ACCESS_KEY"),
|
|
"clientStatus": util.system.get_sys_info(),
|
|
"templateList": [
|
|
{"id": t.get("id", ""), "updateTime": t.get("updateTime", "")}
|
|
for t in template_service.templates.values()
|
|
],
|
|
},
|
|
timeout=10,
|
|
)
|
|
response.raise_for_status()
|
|
except requests.RequestException as e:
|
|
logger.error("请求失败!", e)
|
|
return []
|
|
data = response.json()
|
|
logger.debug("获取任务结果:【%s】", data)
|
|
if data.get("code", 0) == 200:
|
|
templates = data.get("data", {}).get("templates", [])
|
|
tasks = data.get("data", {}).get("tasks", [])
|
|
else:
|
|
tasks = []
|
|
templates = []
|
|
logger.warning("获取任务失败")
|
|
if os.getenv("REDIRECT_TO_URL", False) != False:
|
|
for task in tasks:
|
|
_sess = requests.Session()
|
|
logger.info(
|
|
"重定向任务【%s】至配置的地址:%s",
|
|
task.get("id"),
|
|
os.getenv("REDIRECT_TO_URL"),
|
|
)
|
|
url = f"{os.getenv('REDIRECT_TO_URL')}{task.get('id')}"
|
|
threading.Thread(target=requests.post, args=(url,)).start()
|
|
return []
|
|
for template in templates:
|
|
template_id = template.get("id", "")
|
|
if template_id:
|
|
logger.info("更新模板:【%s】", template_id)
|
|
template_service.download_template(template_id)
|
|
return tasks
|
|
|
|
|
|
def get_template_info(template_id):
|
|
"""
|
|
通过接口获取模板信息
|
|
:rtype: Template
|
|
:param template_id: 模板id
|
|
:type template_id: str
|
|
:return: 模板信息
|
|
"""
|
|
tracer = get_tracer(__name__)
|
|
with tracer.start_as_current_span("get_template_info"):
|
|
with tracer.start_as_current_span("get_template_info.request") as req_span:
|
|
try:
|
|
req_span.set_attribute("http.method", "POST")
|
|
req_span.set_attribute(
|
|
"http.url",
|
|
"{0}/template/{1}".format(os.getenv("API_ENDPOINT"), template_id),
|
|
)
|
|
response = session.post(
|
|
"{0}/template/{1}".format(os.getenv("API_ENDPOINT"), template_id),
|
|
json={
|
|
"accessKey": os.getenv("ACCESS_KEY"),
|
|
},
|
|
timeout=10,
|
|
)
|
|
req_span.set_attribute("http.status_code", response.status_code)
|
|
req_span.set_attribute("http.response", response.text)
|
|
response.raise_for_status()
|
|
except requests.RequestException as e:
|
|
req_span.set_attribute("api.error", str(e))
|
|
logger.error("请求失败!", e)
|
|
return None
|
|
data = response.json()
|
|
logger.debug("获取模板信息结果:【%s】", data)
|
|
remote_template_info = data.get("data", {})
|
|
if not remote_template_info:
|
|
logger.warning("获取模板信息结果为空", data)
|
|
return None
|
|
template = {
|
|
"id": template_id,
|
|
"updateTime": remote_template_info.get("updateTime", template_id),
|
|
"scenic_name": remote_template_info.get("scenicName", "景区"),
|
|
"name": remote_template_info.get("name", "模版"),
|
|
"video_size": remote_template_info.get("resolution", "1920x1080"),
|
|
"frame_rate": 25,
|
|
"overall_duration": 30,
|
|
"video_parts": [],
|
|
}
|
|
|
|
def _template_normalizer(template_info):
|
|
_template = {}
|
|
_placeholder_type = template_info.get("isPlaceholder", -1)
|
|
if _placeholder_type == 0:
|
|
# 固定视频
|
|
_template["source"] = template_info.get("sourceUrl", "")
|
|
elif _placeholder_type == 1:
|
|
# 占位符
|
|
_template["source"] = "PLACEHOLDER_" + template_info.get(
|
|
"sourceUrl", ""
|
|
)
|
|
_template["mute"] = template_info.get("mute", True)
|
|
_template["crop_mode"] = template_info.get("cropEnable", None)
|
|
_template["zoom_cut"] = template_info.get("zoomCut", None)
|
|
else:
|
|
_template["source"] = None
|
|
_overlays = template_info.get("overlays", "")
|
|
if _overlays:
|
|
_template["overlays"] = _overlays.split(",")
|
|
_audios = template_info.get("audios", "")
|
|
if _audios:
|
|
_template["audios"] = _audios.split(",")
|
|
_luts = template_info.get("luts", "")
|
|
if _luts:
|
|
_template["luts"] = _luts.split(",")
|
|
_only_if = template_info.get("onlyIf", "")
|
|
if _only_if:
|
|
_template["only_if"] = _only_if
|
|
_effects = template_info.get("effects", "")
|
|
if _effects:
|
|
_template["effects"] = _effects.split("|")
|
|
return _template
|
|
|
|
# outer template definition
|
|
overall_template = _template_normalizer(remote_template_info)
|
|
template["overall_template"] = overall_template
|
|
# inter template definition
|
|
inter_template_list = remote_template_info.get("children", [])
|
|
for children_template in inter_template_list:
|
|
parts = _template_normalizer(children_template)
|
|
template["video_parts"].append(parts)
|
|
template["local_path"] = os.path.join(
|
|
os.getenv("TEMPLATE_DIR"), str(template_id)
|
|
)
|
|
with get_tracer("api").start_as_current_span(
|
|
"get_template_info.template"
|
|
) as res_span:
|
|
res_span.set_attribute("normalized.response", json.dumps(template))
|
|
return template
|
|
|
|
|
|
def report_task_success(task_info, **kwargs):
|
|
tracer = get_tracer(__name__)
|
|
with tracer.start_as_current_span("report_task_success"):
|
|
with tracer.start_as_current_span("report_task_success.request") as req_span:
|
|
try:
|
|
req_span.set_attribute("http.method", "POST")
|
|
req_span.set_attribute(
|
|
"http.url",
|
|
"{0}/{1}/success".format(
|
|
os.getenv("API_ENDPOINT"), task_info.get("id")
|
|
),
|
|
)
|
|
response = session.post(
|
|
"{0}/{1}/success".format(
|
|
os.getenv("API_ENDPOINT"), task_info.get("id")
|
|
),
|
|
json={"accessKey": os.getenv("ACCESS_KEY"), **kwargs},
|
|
timeout=10,
|
|
)
|
|
req_span.set_attribute("http.status_code", response.status_code)
|
|
req_span.set_attribute("http.response", response.text)
|
|
response.raise_for_status()
|
|
req_span.set_status(Status(StatusCode.OK))
|
|
except requests.RequestException as e:
|
|
req_span.set_attribute("api.error", str(e))
|
|
logger.error("请求失败!", e)
|
|
return None
|
|
|
|
|
|
def report_task_start(task_info):
|
|
tracer = get_tracer(__name__)
|
|
with tracer.start_as_current_span("report_task_start"):
|
|
with tracer.start_as_current_span("report_task_start.request") as req_span:
|
|
try:
|
|
req_span.set_attribute("http.method", "POST")
|
|
req_span.set_attribute(
|
|
"http.url",
|
|
"{0}/{1}/start".format(
|
|
os.getenv("API_ENDPOINT"), task_info.get("id")
|
|
),
|
|
)
|
|
response = session.post(
|
|
"{0}/{1}/start".format(
|
|
os.getenv("API_ENDPOINT"), task_info.get("id")
|
|
),
|
|
json={
|
|
"accessKey": os.getenv("ACCESS_KEY"),
|
|
},
|
|
timeout=10,
|
|
)
|
|
req_span.set_attribute("http.status_code", response.status_code)
|
|
req_span.set_attribute("http.response", response.text)
|
|
response.raise_for_status()
|
|
req_span.set_status(Status(StatusCode.OK))
|
|
except requests.RequestException as e:
|
|
req_span.set_attribute("api.error", str(e))
|
|
logger.error("请求失败!", e)
|
|
return None
|
|
|
|
|
|
def report_task_failed(task_info, reason=""):
|
|
tracer = get_tracer(__name__)
|
|
with tracer.start_as_current_span("report_task_failed") as span:
|
|
span.set_attribute("task_id", task_info.get("id"))
|
|
span.set_attribute("reason", reason)
|
|
with tracer.start_as_current_span("report_task_failed.request") as req_span:
|
|
try:
|
|
req_span.set_attribute("http.method", "POST")
|
|
req_span.set_attribute(
|
|
"http.url",
|
|
"{0}/{1}/fail".format(
|
|
os.getenv("API_ENDPOINT"), task_info.get("id")
|
|
),
|
|
)
|
|
response = session.post(
|
|
"{0}/{1}/fail".format(
|
|
os.getenv("API_ENDPOINT"), task_info.get("id")
|
|
),
|
|
json={"accessKey": os.getenv("ACCESS_KEY"), "reason": reason},
|
|
timeout=10,
|
|
)
|
|
req_span.set_attribute("http.status_code", response.status_code)
|
|
req_span.set_attribute("http.response", response.text)
|
|
response.raise_for_status()
|
|
req_span.set_status(Status(StatusCode.OK))
|
|
except requests.RequestException as e:
|
|
req_span.set_attribute("api.error", str(e))
|
|
req_span.set_status(Status(StatusCode.ERROR))
|
|
logger.error("请求失败!", e)
|
|
return None
|
|
|
|
|
|
def upload_task_file(task_info, ffmpeg_task):
|
|
tracer = get_tracer(__name__)
|
|
with get_tracer("api").start_as_current_span("upload_task_file") as span:
|
|
logger.info("开始上传文件: %s", task_info.get("id"))
|
|
span.set_attribute("file.id", task_info.get("id"))
|
|
with tracer.start_as_current_span(
|
|
"upload_task_file.request_upload_url"
|
|
) as req_span:
|
|
try:
|
|
req_span.set_attribute("http.method", "POST")
|
|
req_span.set_attribute(
|
|
"http.url",
|
|
"{0}/{1}/uploadUrl".format(
|
|
os.getenv("API_ENDPOINT"), task_info.get("id")
|
|
),
|
|
)
|
|
response = session.post(
|
|
"{0}/{1}/uploadUrl".format(
|
|
os.getenv("API_ENDPOINT"), task_info.get("id")
|
|
),
|
|
json={
|
|
"accessKey": os.getenv("ACCESS_KEY"),
|
|
},
|
|
timeout=10,
|
|
)
|
|
req_span.set_attribute("http.status_code", response.status_code)
|
|
req_span.set_attribute("http.response", response.text)
|
|
response.raise_for_status()
|
|
req_span.set_status(Status(StatusCode.OK))
|
|
except requests.RequestException as e:
|
|
span.set_attribute("api.error", str(e))
|
|
req_span.set_status(Status(StatusCode.ERROR))
|
|
logger.error("请求失败!", e)
|
|
return False
|
|
data = response.json()
|
|
url = data.get("data", "")
|
|
logger.info("开始上传文件: %s 至 %s", task_info.get("id"), url)
|
|
return oss.upload_to_oss(url, ffmpeg_task.get_output_file())
|
|
|
|
|
|
def get_task_info(id):
|
|
try:
|
|
response = session.get(
|
|
os.getenv("API_ENDPOINT") + "/" + id + "/info",
|
|
params={
|
|
"accessKey": os.getenv("ACCESS_KEY"),
|
|
},
|
|
timeout=10,
|
|
)
|
|
response.raise_for_status()
|
|
except requests.RequestException as e:
|
|
logger.error("请求失败!", e)
|
|
return []
|
|
data = response.json()
|
|
logger.debug("获取任务结果:【%s】", data)
|
|
if data.get("code", 0) == 200:
|
|
return data.get("data", {})
|