Compare commits

..

1 Commits

Author SHA1 Message Date
CI Test b87d7b763e chore(frontend): Phase 1 技术债务清理 - 删除死代码和重复样式
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 58s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 2m7s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 3m47s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 5m5s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
- 删除 src/config/navigation.tsx(废弃文件,211行)
- 删除 src/components/business/business.css(死CSS,365行)
- 删除 src/api/dashboard.ts(废弃API模块,42行)
- 移除 router/index.tsx 重复 my-voices 路由(7行)
- 清理 generate.css 重复按钮样式(48行,改用 ui.css 统一样式)
- 清理 Admin.css 重复 .xx-card/.xx-select 定义(40行)

共减少约 713 行代码,vite build 验证通过
2026-07-13 14:12:00 +08:00
8 changed files with 38 additions and 811 deletions
-42
View File
@@ -1,42 +0,0 @@
/**
* 仪表盘 API
* Phase 1 新增:用户仪表盘概览
*/
import apiClient from "./client";
/** 仪表盘概览数据 */
export interface DashboardOverview {
/** 素材总数 */
total_assets: number;
/** 已用存储(字节) */
used_storage_bytes: number;
/** 总标题数 */
total_titles: number;
/** 总配音数 */
total_voices: number;
/** 生成任务总数 */
total_tasks: number;
/** 成品总数 */
total_products: number;
/** 最近生成任务 */
recent_tasks: Array<{
id: string;
task_type: string;
status: string;
progress: number;
user_message: string;
created_at: string;
}>;
/** 订阅信息 */
subscription: {
plan: "free" | "pro" | "enterprise";
status: "active" | "inactive" | "expired";
expires_at?: string;
};
}
/** 获取仪表盘概览数据 */
export const getDashboardOverview = async (): Promise<DashboardOverview> => {
const response = await apiClient.get("/dashboard/overview");
return response.data;
};
@@ -1,365 +0,0 @@
/* V21 业务组件统一样式 */
/* ==================== 按钮 ==================== */
.xx-primary-btn {
background: var(--gradient-primary) !important;
color: var(--text-inverse) !important;
border: none !important;
border-radius: var(--radius-md) !important;
padding: 10px 20px !important;
font-weight: var(--font-weight-bold) !important;
box-shadow: var(--shadow-primary) !important;
transition: var(--transition-all) !important;
cursor: pointer;
height: auto !important;
}
.xx-primary-btn:hover {
box-shadow: var(--shadow-hover) !important;
transform: translateY(-1px);
}
.xx-ghost-btn {
background: transparent !important;
color: var(--primary-color) !important;
border: 2px solid var(--primary-color) !important;
border-radius: var(--radius-md) !important;
padding: var(--space-sm) 18px !important;
font-weight: var(--font-weight-bold) !important;
transition: var(--transition-all) !important;
cursor: pointer;
height: auto !important;
}
.xx-ghost-btn:hover {
background: var(--primary-soft) !important;
}
/* ==================== 卡片 ==================== */
.xx-card {
background: var(--bg-elevated);
border: 1px solid var(--border-color);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-card);
padding: var(--space-lg);
margin-bottom: 20px;
transition: all var(--transition-slow);
}
.xx-card:hover {
box-shadow: var(--shadow-md);
transform: translateY(-2px);
}
/* ==================== 页面结构 ==================== */
.xx-page {
max-width: 1200px;
margin: 0 auto;
padding: var(--space-lg);
}
.xx-page-head {
display: flex;
justify-content: space-between;
align-items: flex-start;
gap: 18px;
margin-bottom: 28px;
}
.xx-page-head h2 {
font-size: 26px;
font-weight: var(--font-weight-extrabold);
color: var(--text-primary);
margin: 0 0 var(--space-sm);
}
.xx-page-head p {
font-size: var(--font-size-base);
color: var(--text-secondary);
margin: 0;
}
/* ==================== 表格样式 ==================== */
.xx-table-card {
background: var(--bg-elevated);
border: 1px solid var(--border-color);
border-radius: var(--radius-xl);
box-shadow: var(--shadow-card);
padding: 20px;
overflow: hidden;
}
/* 表格包装器 */
.xx-table-wrapper {
border-radius: var(--radius-lg);
overflow: hidden;
}
/* ==================== 标签/Tag ==================== */
.xx-tag {
padding: var(--space-xs) 12px;
border-radius: var(--radius-xs);
font-size: 13px;
font-weight: var(--font-weight-medium);
}
.xx-tag-indigo {
background: var(--primary-soft);
color: var(--primary-color);
border: 1px solid var(--color-primary-200);
}
.xx-tag-success {
background: var(--success-soft);
color: var(--color-secondary-500);
border: 1px solid var(--success-border);
}
.xx-tag-warning {
background: var(--warning-soft);
color: var(--accent-dark);
border: 1px solid var(--color-accent-200);
}
.xx-tag-error {
background: var(--error-soft);
color: var(--error-color);
border: 1px solid var(--error-border);
}
/* ==================== 搜索栏 ==================== */
.xx-search-bar {
margin-bottom: 20px;
}
.xx-search-input {
width: 100%;
padding: 12px 18px;
border: 2px solid var(--border-color);
border-radius: var(--radius-md);
font-size: var(--font-size-base);
background: var(--bg-primary);
transition: var(--transition-all);
outline: none;
}
.xx-search-input:focus {
border-color: var(--primary-color);
box-shadow: 0 0 0 4px
color-mix(in srgb, var(--primary-color) 10%, transparent);
}
/* ==================== Modal ==================== */
.xx-modal .ant-modal-content {
border-radius: var(--radius-xl);
padding: var(--space-lg);
}
.xx-modal .ant-modal-header {
border-radius: var(--radius-xl) var(--radius-xl) 0 0;
padding: 20px var(--space-lg);
border-bottom: 1px solid var(--border-color);
}
.xx-modal .ant-modal-title {
font-size: var(--font-size-lg);
font-weight: var(--font-weight-bold);
color: var(--text-primary);
}
.xx-modal .ant-modal-footer {
border-top: 1px solid var(--border-color);
padding: var(--space-md) var(--space-lg);
}
/* ==================== 空状态 ==================== */
.xx-empty-state {
text-align: center;
padding: var(--space-3xl) var(--space-lg);
color: var(--text-secondary);
}
.xx-empty-state-icon {
font-size: 48px;
margin-bottom: var(--space-md);
}
/* ==================== 网格布局 ==================== */
.xx-grid-2 {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20px;
}
.xx-grid-3 {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 20px;
}
.xx-grid-4 {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20px;
}
@media (max-width: 768px) {
.xx-grid-2,
.xx-grid-3,
.xx-grid-4 {
grid-template-columns: 1fr;
}
}
/* ==================== 配额展示 ==================== */
.xx-quota-item {
padding: 20px;
background: var(--bg-primary);
border: 1px solid var(--border-color);
border-radius: var(--radius-lg);
transition: var(--transition-all);
}
.xx-quota-item:hover {
border-color: var(--primary-color);
box-shadow: 0 8px 24px
color-mix(in srgb, var(--primary-color) 10%, transparent);
}
/* ==================== 进度条 ==================== */
.xx-progress {
margin-top: 12px;
}
/* ==================== Ant Design 覆盖样式 ==================== */
/* Table overrides */
.ant-table-wrapper .ant-table-thead > tr > th {
background: var(--bg-secondary) !important;
font-weight: var(--font-weight-bold) !important;
color: var(--text-primary) !important;
border-bottom: 2px solid var(--border-color) !important;
padding: 14px var(--space-md) !important;
}
.ant-table-wrapper .ant-table-tbody > tr > td {
padding: 14px var(--space-md) !important;
border-bottom: 1px solid var(--color-gray-100) !important;
}
.ant-table-wrapper .ant-table-tbody > tr:hover > td {
background: var(--color-gray-50) !important;
}
/* Card overrides */
.ant-card {
border-radius: var(--radius-xl) !important;
border: 1px solid var(--border-color) !important;
}
.ant-card-head {
border-bottom: 1px solid var(--border-color) !important;
min-height: 52px !important;
padding: 0 var(--space-lg) !important;
}
.ant-card-head-title {
font-weight: var(--font-weight-bold) !important;
font-size: var(--font-size-md) !important;
color: var(--text-primary) !important;
}
.ant-card-body {
padding: 20px var(--space-lg) !important;
}
/* Modal overrides */
.ant-modal-content {
border-radius: var(--radius-xl) !important;
overflow: hidden;
}
.ant-modal-header {
padding: 20px var(--space-lg) !important;
background: var(--bg-primary) !important;
}
.ant-modal-title {
font-weight: var(--font-weight-bold) !important;
font-size: var(--font-size-lg) !important;
color: var(--text-primary) !important;
}
.ant-modal-body {
padding: var(--space-lg) !important;
}
.ant-modal-footer {
padding: var(--space-md) var(--space-lg) !important;
}
/* Button overrides */
.ant-btn-primary {
background: var(--gradient-primary) !important;
border: none !important;
border-radius: var(--radius-md) !important;
box-shadow: var(--shadow-primary) !important;
height: auto !important;
padding: 10px 20px !important;
font-weight: var(--font-weight-bold) !important;
}
.ant-btn-primary:hover {
background: var(--gradient-primary) !important;
box-shadow: var(--shadow-hover) !important;
transform: translateY(-1px);
}
/* Tag overrides */
.ant-tag {
border-radius: var(--radius-xs) !important;
padding: var(--space-xs) 12px !important;
font-weight: var(--font-weight-medium) !important;
}
/* Select overrides */
.ant-select-selector {
border-radius: var(--radius-md) !important;
border-color: var(--border-color) !important;
}
.ant-select:not(.ant-select-disabled):hover .ant-select-selector {
border-color: var(--primary-color) !important;
}
.ant-select-focused .ant-select-selector {
border-color: var(--primary-color) !important;
box-shadow: 0 0 0 3px
color-mix(in srgb, var(--primary-color) 10%, transparent) !important;
}
/* Input overrides */
.ant-input {
border-radius: var(--radius-md) !important;
border-color: var(--border-color) !important;
padding: 10px 14px !important;
}
.ant-input:hover {
border-color: var(--primary-color) !important;
}
.ant-input:focus {
border-color: var(--primary-color) !important;
box-shadow: 0 0 0 3px
color-mix(in srgb, var(--primary-color) 10%, transparent) !important;
}
/* Progress overrides */
.ant-progress-inner {
background: var(--color-gray-100) !important;
border-radius: var(--radius-xs) !important;
}
.ant-progress-bg {
border-radius: var(--radius-xs) !important;
}
-211
View File
@@ -1,211 +0,0 @@
/**
* 统一导航配置
* Header 和 Sidebar 共用此数据源
*/
import React from "react";
import {
DashboardOutlined,
VideoCameraOutlined,
FileOutlined,
AudioOutlined,
FileTextOutlined,
TrophyOutlined,
AppstoreOutlined,
HistoryOutlined,
ControlOutlined,
CrownOutlined,
ScanOutlined,
EditOutlined,
FolderOutlined,
} from "@ant-design/icons";
/** 导航项定义 */
export interface NavItem {
key: string;
label: string;
path: string;
icon: React.ReactNode;
}
/** 导航分组定义 */
export interface NavGroup {
title: string;
items: NavItem[];
}
/**
* 扁平导航列表(Header 使用)
*/
export const NAV_ITEMS: NavItem[] = [
{
key: "dashboard",
label: "概览",
path: "/app/dashboard",
icon: <DashboardOutlined />,
},
{
key: "assets",
label: "素材库",
path: "/app/assets",
icon: <FileOutlined />,
},
{
key: "titles",
label: "标题库",
path: "/app/titles",
icon: <FileTextOutlined />,
},
{
key: "voices",
label: "配音库",
path: "/app/voices",
icon: <AudioOutlined />,
},
{
key: "voice-clone",
label: "我的音色",
path: "/app/voice-clone",
icon: <AudioOutlined />,
},
{
key: "voice-materials",
label: "配音素材库",
path: "/app/voice-materials",
icon: <AudioOutlined />,
},
{
key: "templates",
label: "模板库",
path: "/app/templates",
icon: <AppstoreOutlined />,
},
{
key: "editing-planner",
label: "剪辑编辑器",
path: "/app/editing-planner",
icon: <EditOutlined />,
},
{
key: "my-templates",
label: "我的模板",
path: "/app/my-templates",
icon: <FolderOutlined />,
},
{
key: "generate",
label: "一键生成",
path: "/app/generate",
icon: <VideoCameraOutlined />,
},
{
key: "history",
label: "任务历史",
path: "/app/history",
icon: <HistoryOutlined />,
},
{
key: "products",
label: "成品库",
path: "/app/products",
icon: <TrophyOutlined />,
},
{
key: "duplication",
label: "查重",
path: "/app/duplication",
icon: <ScanOutlined />,
},
];
/**
* 分组导航列表(Sidebar 使用)
*/
export const NAV_GROUPS: NavGroup[] = [
{
title: "创作工具",
items: [
{
key: "dashboard",
label: "首页",
path: "/app/dashboard",
icon: <DashboardOutlined />,
},
{
key: "generate",
label: "一键生成",
path: "/app/generate",
icon: <VideoCameraOutlined />,
},
],
},
{
title: "资源管理",
items: [
{
key: "assets",
label: "素材库",
path: "/app/assets",
icon: <FileOutlined />,
},
{
key: "voices",
label: "配音库",
path: "/app/voices",
icon: <AudioOutlined />,
},
{
key: "voice-clone",
label: "我的音色",
path: "/app/voice-clone",
icon: <AudioOutlined />,
},
{
key: "voice-materials",
label: "配音素材库",
path: "/app/voice-materials",
icon: <AudioOutlined />,
},
{
key: "titles",
label: "标题库",
path: "/app/titles",
icon: <FileTextOutlined />,
},
{
key: "products",
label: "成片库",
path: "/app/products",
icon: <TrophyOutlined />,
},
{
key: "templates",
label: "模板库",
path: "/app/templates",
icon: <AppstoreOutlined />,
},
],
},
{
title: "系统",
items: [
{
key: "history",
label: "任务历史",
path: "/app/history",
icon: <HistoryOutlined />,
},
{
key: "admin",
label: "控制台",
path: "/app/admin",
icon: <ControlOutlined />,
},
{
key: "subscription",
label: "订阅管理",
path: "/app/subscription",
icon: <CrownOutlined />,
},
],
},
];
-40
View File
@@ -75,35 +75,6 @@
margin: 0;
}
/* V21 卡片 */
.xx-card {
background: rgba(255, 255, 255, 0.94);
border: 1px solid rgba(226, 232, 240, 0.95);
border-radius: var(--radius-lg);
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
padding: 24px;
transition: all 0.3s;
}
.xx-card:hover {
box-shadow: 0 16px 40px rgba(15, 23, 42, 0.08);
}
.xx-card .ant-card-head {
border-bottom: 1px solid rgba(226, 232, 240, 0.8);
padding: 20px 24px;
}
.xx-card .ant-card-head-title {
font-weight: 800;
font-size: 17px;
color: var(--slate, #0f172a);
}
.xx-card .ant-card-body {
padding: 24px;
}
/* 统计卡片网格 - 4列 */
.xx-grid-4 {
display: grid;
@@ -302,17 +273,6 @@
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important;
}
/* V21 Select */
.xx-select {
border-radius: var(--radius-md) !important;
}
.xx-select:hover,
.xx-select:focus {
border-color: var(--indigo, #4f46e5) !important;
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1) !important;
}
/* V21 Tag */
.xx-tag {
border-radius: var(--radius-xs) !important;
-48
View File
@@ -612,54 +612,6 @@
flex: 1;
}
/* ============================================================
按钮(匹配原型 .btn .ghost / .btn .primary
============================================================ */
.xx-btn {
display: inline-flex;
align-items: center;
justify-content: center;
gap: 6px;
height: 42px;
padding: 0 20px;
border-radius: var(--radius-sm);
font-size: 14px;
font-weight: 600;
cursor: pointer;
transition: all 0.15s ease;
border: none;
outline: none;
white-space: nowrap;
}
.xx-btn:disabled {
opacity: 0.5;
cursor: not-allowed;
}
.xx-btn-primary {
background: var(--gradient-primary);
color: var(--text-inverse);
box-shadow: 0 14px 26px rgba(79, 70, 229, 0.22);
}
.xx-btn-primary:hover:not(:disabled) {
transform: translateY(-2px);
box-shadow: 0 18px 34px rgba(79, 70, 229, 0.28);
}
.xx-btn-ghost {
background: var(--bg-primary);
border: 1px solid var(--border-color);
color: var(--text-secondary);
}
.xx-btn-ghost:hover:not(:disabled) {
border-color: var(--info-border);
color: var(--primary-dark);
background: var(--primary-soft);
}
/* ============================================================
右侧预览区 generate-preview
============================================================ */
-7
View File
@@ -170,13 +170,6 @@ export const router = createBrowserRouter([
Component: m.default,
})),
},
{
path: "my-voices",
lazy: () =>
import("@/pages/my-voices/MyVoices").then((m) => ({
Component: m.default,
})),
},
{
path: "accounts",
lazy: () =>
+15 -31
View File
@@ -113,8 +113,8 @@ from video_processing.oss_helpers import (
get_signed_download_url,
upload_to_oss,
)
from video_processing.render_engine_resolver import ENGINE_LEGACY, ENGINE_UNIFIED
from video_processing.unified_render_service import UnifiedRenderService
from video_processing.render_engine_resolver import ENGINE_LEGACY, ENGINE_UNIFIED
# ── 虚拟 Plan / Clip(内存中构建,不写数据库) ────────────────────────────────
@@ -619,8 +619,7 @@ def _render_with_legacy_engine(
import subprocess
main_clips = [
c
for c in virtual_clips
c for c in virtual_clips
if c.clip_type in ("main", "b_roll", "background")
or (c.clip_type == "main" and c.config.get("role") == "b_roll")
]
@@ -675,27 +674,17 @@ def _render_with_legacy_engine(
filter_complex = ";".join(fc_parts)
command = [
FFMPEG_BIN,
"-y",
FFMPEG_BIN, "-y",
*input_args,
"-filter_complex",
filter_complex,
"-map",
video_label,
"-map",
audio_label,
"-c:v",
"libx264",
"-crf",
"23",
"-preset",
"medium",
"-c:a",
"aac",
"-b:a",
"192k",
"-movflags",
"+faststart",
"-filter_complex", filter_complex,
"-map", video_label,
"-map", audio_label,
"-c:v", "libx264",
"-crf", "23",
"-preset", "medium",
"-c:a", "aac",
"-b:a", "192k",
"-movflags", "+faststart",
str(output_path),
]
@@ -705,9 +694,7 @@ def _render_with_legacy_engine(
except subprocess.CalledProcessError as e:
logger.error(
"[task_id=%s] [渲染] legacy 引擎 FFmpeg 失败: %s\nfilter_complex: %s",
task_id,
e,
filter_complex[:500],
task_id, e, filter_complex[:500],
)
raise
@@ -893,9 +880,7 @@ def generate_video(self, task_id: str) -> dict:
render_elapsed = time.monotonic() - render_start
logger.info(
"[task_id=%s] [渲染] legacy 引擎完成: 耗时=%.1fs, 时长=%.2fs",
task_id,
render_elapsed,
render_duration,
task_id, render_elapsed, render_duration,
)
else:
# 新引擎:UnifiedRenderService 图层架构
@@ -916,8 +901,7 @@ def generate_video(self, task_id: str) -> dict:
render_elapsed = time.monotonic() - render_start
logger.info(
"[task_id=%s] [渲染] unified 引擎完成: 耗时=%.1fs",
task_id,
render_elapsed,
task_id, render_elapsed,
)
if gen_task:
+23 -67
View File
@@ -19,9 +19,8 @@ from unittest.mock import MagicMock, patch
os.environ.setdefault("JWT_SECRET_KEY", "unit-test-secret-key-for-testing")
os.environ.setdefault("DATABASE_URL", "sqlite:///test.db")
from pathlib import Path
import pytest
from pathlib import Path
# ── Mock worker 模块以避免数据库连接 ──────────────────────────────────────────
@@ -69,12 +68,11 @@ class _TestClip:
def test_resolver_unified_when_enabled_100_percent():
"""flag 全局开启(percentage=100)时,返回 unified。"""
from video_processing.render_engine_resolver import RenderEngineResolver
from packages.adapters.redis.feature_flag_store import (
FeatureFlagConfig,
InMemoryFeatureFlagStore,
)
from video_processing.render_engine_resolver import RenderEngineResolver
store = InMemoryFeatureFlagStore()
store.set(FeatureFlagConfig(name="render_engine", enabled=True, percentage=100))
@@ -85,12 +83,11 @@ def test_resolver_unified_when_enabled_100_percent():
def test_resolver_legacy_when_flag_disabled():
"""flag 全局关闭时,返回默认引擎 legacy。"""
from video_processing.render_engine_resolver import RenderEngineResolver
from packages.adapters.redis.feature_flag_store import (
FeatureFlagConfig,
InMemoryFeatureFlagStore,
)
from video_processing.render_engine_resolver import RenderEngineResolver
store = InMemoryFeatureFlagStore()
store.set(FeatureFlagConfig(name="render_engine", enabled=False, percentage=100))
@@ -101,12 +98,11 @@ def test_resolver_legacy_when_flag_disabled():
def test_resolver_whitelist_overrides_percentage_0():
"""白名单用户即使 percentage=0 也走 unified。"""
from video_processing.render_engine_resolver import RenderEngineResolver
from packages.adapters.redis.feature_flag_store import (
FeatureFlagConfig,
InMemoryFeatureFlagStore,
)
from video_processing.render_engine_resolver import RenderEngineResolver
store = InMemoryFeatureFlagStore()
store.set(
@@ -125,12 +121,11 @@ def test_resolver_whitelist_overrides_percentage_0():
def test_resolver_percentage_0_all_legacy():
"""percentage=0 且无白名单时,全部走 legacy。"""
from video_processing.render_engine_resolver import RenderEngineResolver
from packages.adapters.redis.feature_flag_store import (
FeatureFlagConfig,
InMemoryFeatureFlagStore,
)
from video_processing.render_engine_resolver import RenderEngineResolver
store = InMemoryFeatureFlagStore()
store.set(FeatureFlagConfig(name="render_engine", enabled=True, percentage=0))
@@ -142,12 +137,11 @@ def test_resolver_percentage_0_all_legacy():
def test_resolver_default_unified_when_flag_off():
"""默认引擎设为 unified 且 flag 关闭时,返回 unified。"""
from video_processing.render_engine_resolver import RenderEngineResolver
from packages.adapters.redis.feature_flag_store import (
FeatureFlagConfig,
InMemoryFeatureFlagStore,
)
from video_processing.render_engine_resolver import RenderEngineResolver
store = InMemoryFeatureFlagStore()
store.set(FeatureFlagConfig(name="render_engine", enabled=False, percentage=0))
@@ -176,23 +170,11 @@ def test_legacy_engine_single_clip_keeps_original_fps():
# 生成 1 秒 30fps 测试视频(带音频)
subprocess.run(
[
"ffmpeg",
"-y",
"-f",
"lavfi",
"-i",
"color=c=red:s=640x360:d=1:r=30",
"-f",
"lavfi",
"-i",
"anullsrc=r=44100:cl=stereo:d=1",
"-c:v",
"libx264",
"-pix_fmt",
"yuv420p",
"-c:a",
"aac",
"-shortest",
"ffmpeg", "-y",
"-f", "lavfi", "-i", "color=c=red:s=640x360:d=1:r=30",
"-f", "lavfi", "-i", "anullsrc=r=44100:cl=stereo:d=1",
"-c:v", "libx264", "-pix_fmt", "yuv420p",
"-c:a", "aac", "-shortest",
str(input_path),
],
check=True,
@@ -240,23 +222,11 @@ def test_legacy_engine_two_clips_concat_duration():
color = "red" if idx == 0 else "blue"
subprocess.run(
[
"ffmpeg",
"-y",
"-f",
"lavfi",
"-i",
f"color=c={color}:s=640x360:d=1:r=30",
"-f",
"lavfi",
"-i",
"anullsrc=r=44100:cl=stereo:d=1",
"-c:v",
"libx264",
"-pix_fmt",
"yuv420p",
"-c:a",
"aac",
"-shortest",
"ffmpeg", "-y",
"-f", "lavfi", "-i", f"color=c={color}:s=640x360:d=1:r=30",
"-f", "lavfi", "-i", "anullsrc=r=44100:cl=stereo:d=1",
"-c:v", "libx264", "-pix_fmt", "yuv420p",
"-c:a", "aac", "-shortest",
str(inp),
],
check=True,
@@ -294,23 +264,11 @@ def test_legacy_engine_broll_mode_supported():
subprocess.run(
[
"ffmpeg",
"-y",
"-f",
"lavfi",
"-i",
"color=c=green:s=640x360:d=1:r=30",
"-f",
"lavfi",
"-i",
"anullsrc=r=44100:cl=stereo:d=1",
"-c:v",
"libx264",
"-pix_fmt",
"yuv420p",
"-c:a",
"aac",
"-shortest",
"ffmpeg", "-y",
"-f", "lavfi", "-i", "color=c=green:s=640x360:d=1:r=30",
"-f", "lavfi", "-i", "anullsrc=r=44100:cl=stereo:d=1",
"-c:v", "libx264", "-pix_fmt", "yuv420p",
"-c:a", "aac", "-shortest",
str(input_path),
],
check=True,
@@ -318,10 +276,8 @@ def test_legacy_engine_broll_mode_supported():
)
clip = _TestClip(
asset_id="asset-1",
duration=1.0,
clip_type="main",
config={"role": "b_roll"},
asset_id="asset-1", duration=1.0,
clip_type="main", config={"role": "b_roll"},
)
asset_path_map = {"asset-1": input_path}