feat(core/backend): pipeline continuity + threaded ffmpeg burn-in export + upload/save-timeline

Video pipeline (script→assets→storyboard→video→stitch):
- robust split_script_into_segments (4 non-empty scenes), scene-aware storyboard/video prompts
- link VideoSegment→ScriptSegment + storyboard-frame reference image (graceful text fallback)
- idempotent poll_video_segment (no double-charge on repeated polling)
- threaded export (no Celery worker needed) + poll-export endpoint
- run_export_job rewritten to filter_complex: per-clip trim, xfade transitions,
  subtitle burn-in (Pillow PNG overlay; this ffmpeg lacks libass), BGM mix
- upload-video-segment / upload-bgm / save-timeline endpoints
- serializers embed asset preview URLs (beat assets pagination); Pillow added to requirements

Also includes prior uncommitted backend work: account preferences/sessions,
billing trend, product/asset endpoints, accounts 0002 migration.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
zyc
2026-06-09 14:46:16 +08:00
co-authored by Claude Opus 4.8
parent 8959946241
commit 92826dec14
13 changed files with 1229 additions and 97 deletions
+8
View File
@@ -3,9 +3,13 @@ from django.urls import path
from .views import (
change_password,
login,
login_sessions,
logout,
me,
preferences,
register,
revoke_login_session,
revoke_other_sessions,
team_member_detail,
team_member_password,
team_members,
@@ -20,6 +24,10 @@ urlpatterns = [
path("me/", me, name="auth-me"),
path("me/password/", change_password, name="auth-change-password"),
path("me/avatar/", update_avatar, name="auth-avatar"),
path("me/preferences/", preferences, name="auth-preferences"),
path("me/sessions/", login_sessions, name="auth-sessions"),
path("me/sessions/revoke-others/", revoke_other_sessions, name="auth-sessions-revoke-others"),
path("me/sessions/<uuid:session_id>/revoke/", revoke_login_session, name="auth-session-revoke"),
path("team/members/", team_members, name="team-members"),
path("team/members/<uuid:member_id>/", team_member_detail, name="team-member-detail"),
path("team/members/<uuid:member_id>/password/", team_member_password, name="team-member-password"),