Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 63b0bde41a | |||
| 9784aed605 |
Executable → Regular
+6
-13
@@ -1,24 +1,17 @@
|
|||||||
"""
|
"""
|
||||||
视频处理模块
|
视频处理模块
|
||||||
|
|
||||||
|
轻量工具(ffmpeg_utils / oss_helpers / dedup_helpers)顶层直接导出,
|
||||||
|
无额外依赖。渲染相关组件(UnifiedRenderService / RenderAdapter /
|
||||||
|
VideoProcessor 等)按需从子模块导入,避免 __init__ 阶段引入
|
||||||
|
packages / DB 等重依赖。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# 共享工具模块(供 editing_modes / generation / edit_plan_generation 等复用)
|
# 共享工具模块(零外部依赖,供 editing_modes / generation / edit_plan_generation 等复用)
|
||||||
from . import dedup_helpers, ffmpeg_utils, oss_helpers
|
from . import dedup_helpers, ffmpeg_utils, oss_helpers
|
||||||
from .processor import VideoProcessor, VideoResult
|
|
||||||
from .render_adapter import RenderAdapter, RenderAdapterResult
|
|
||||||
from .render_engine_resolver import RenderEngineResolver, get_render_engine_resolver
|
|
||||||
from .unified_render_service import RenderResult, UnifiedRenderService
|
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"VideoProcessor",
|
|
||||||
"VideoResult",
|
|
||||||
"ffmpeg_utils",
|
"ffmpeg_utils",
|
||||||
"oss_helpers",
|
"oss_helpers",
|
||||||
"dedup_helpers",
|
"dedup_helpers",
|
||||||
"UnifiedRenderService",
|
|
||||||
"RenderResult",
|
|
||||||
"RenderAdapter",
|
|
||||||
"RenderAdapterResult",
|
|
||||||
"RenderEngineResolver",
|
|
||||||
"get_render_engine_resolver",
|
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -116,6 +116,15 @@ def render_edit_plan(self, plan_id: str) -> dict:
|
|||||||
rendered_clip_ids: list[str] = []
|
rendered_clip_ids: list[str] = []
|
||||||
failed_clip_ids: list[str] = []
|
failed_clip_ids: list[str] = []
|
||||||
|
|
||||||
|
# 预先批量查询所有素材的 storage_key(file_url)
|
||||||
|
from packages.adapters.sqlalchemy_impl.models import AssetModel
|
||||||
|
|
||||||
|
clip_asset_ids = [c.asset_id for c in clips if c.asset_id]
|
||||||
|
asset_storage_map: dict[str, str] = {}
|
||||||
|
if clip_asset_ids:
|
||||||
|
assets = db.query(AssetModel).filter(AssetModel.id.in_(clip_asset_ids)).all()
|
||||||
|
asset_storage_map = {a.id: a.file_url for a in assets if a.file_url}
|
||||||
|
|
||||||
for clip in clips:
|
for clip in clips:
|
||||||
if not clip.asset_id:
|
if not clip.asset_id:
|
||||||
# 没有素材的片段跳过,标记为失败
|
# 没有素材的片段跳过,标记为失败
|
||||||
@@ -129,10 +138,22 @@ def render_edit_plan(self, plan_id: str) -> dict:
|
|||||||
rendered_clip_ids.append(clip.id)
|
rendered_clip_ids.append(clip.id)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
storage_key = asset_storage_map.get(clip.asset_id)
|
||||||
|
if not storage_key:
|
||||||
|
logger.warning(
|
||||||
|
"片段素材无 storage_key,跳过: clip_id=%s asset_id=%s",
|
||||||
|
clip.id,
|
||||||
|
clip.asset_id,
|
||||||
|
)
|
||||||
|
clip.mark_failed()
|
||||||
|
clip_repo.update(clip)
|
||||||
|
failed_clip_ids.append(clip.id)
|
||||||
|
continue
|
||||||
|
|
||||||
# 下载素材
|
# 下载素材
|
||||||
ext = Path(clip.asset_id).suffix or ".mp4"
|
ext = Path(storage_key).suffix or ".mp4"
|
||||||
local_path = tmpdir_path / f"clip_{clip.order:04d}{ext}"
|
local_path = tmpdir_path / f"clip_{clip.order:04d}{ext}"
|
||||||
if download_asset(clip.asset_id, local_path):
|
if download_asset(storage_key, local_path):
|
||||||
asset_path_map[clip.asset_id] = local_path
|
asset_path_map[clip.asset_id] = local_path
|
||||||
rendered_clip_ids.append(clip.id)
|
rendered_clip_ids.append(clip.id)
|
||||||
else:
|
else:
|
||||||
|
|||||||
@@ -162,13 +162,15 @@ def _build_plan_and_clips_from_task(
|
|||||||
"""
|
"""
|
||||||
plan = _VirtualPlan(id=task_id, name=f"Generated-{task_id[:8]}")
|
plan = _VirtualPlan(id=task_id, name=f"Generated-{task_id[:8]}")
|
||||||
|
|
||||||
# 为每个下载路径生成合成 asset_id
|
# 为每个下载路径生成合成 asset_id,并预探测素材时长
|
||||||
asset_path_map: dict[str, Path] = {}
|
asset_path_map: dict[str, Path] = {}
|
||||||
path_to_asset_id: dict[Path, str] = {}
|
path_to_asset_id: dict[Path, str] = {}
|
||||||
|
path_duration: dict[Path, float] = {}
|
||||||
for i, p in enumerate(downloaded_paths):
|
for i, p in enumerate(downloaded_paths):
|
||||||
asset_id = f"gen_{task_id[:8]}_{i:03d}{p.suffix or '.mp4'}"
|
asset_id = f"gen_{task_id[:8]}_{i:03d}{p.suffix or '.mp4'}"
|
||||||
asset_path_map[asset_id] = p
|
asset_path_map[asset_id] = p
|
||||||
path_to_asset_id[p] = asset_id
|
path_to_asset_id[p] = asset_id
|
||||||
|
path_duration[p] = probe_duration(p)
|
||||||
|
|
||||||
clips: list[_VirtualClip] = []
|
clips: list[_VirtualClip] = []
|
||||||
n = len(downloaded_paths)
|
n = len(downloaded_paths)
|
||||||
@@ -184,6 +186,7 @@ def _build_plan_and_clips_from_task(
|
|||||||
clip_type=clip_type,
|
clip_type=clip_type,
|
||||||
order=i,
|
order=i,
|
||||||
asset_id=path_to_asset_id[p],
|
asset_id=path_to_asset_id[p],
|
||||||
|
duration=path_duration[p],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif mode == "voice_over":
|
elif mode == "voice_over":
|
||||||
@@ -196,6 +199,7 @@ def _build_plan_and_clips_from_task(
|
|||||||
clip_type="main",
|
clip_type="main",
|
||||||
order=i,
|
order=i,
|
||||||
asset_id=path_to_asset_id[p],
|
asset_id=path_to_asset_id[p],
|
||||||
|
duration=path_duration[p],
|
||||||
config={"role": "b_roll"},
|
config={"role": "b_roll"},
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -215,6 +219,7 @@ def _build_plan_and_clips_from_task(
|
|||||||
clip_type=clip_type,
|
clip_type=clip_type,
|
||||||
order=i,
|
order=i,
|
||||||
asset_id=path_to_asset_id[p],
|
asset_id=path_to_asset_id[p],
|
||||||
|
duration=path_duration[p],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
@@ -227,6 +232,7 @@ def _build_plan_and_clips_from_task(
|
|||||||
clip_type="main",
|
clip_type="main",
|
||||||
order=i,
|
order=i,
|
||||||
asset_id=path_to_asset_id[p],
|
asset_id=path_to_asset_id[p],
|
||||||
|
duration=path_duration[p],
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user