diff --git a/components/canvas/LiblibVideoCanvasReplica.tsx b/components/canvas/LiblibVideoCanvasReplica.tsx index 9a9a5c9d9..b1ac018cd 100644 --- a/components/canvas/LiblibVideoCanvasReplica.tsx +++ b/components/canvas/LiblibVideoCanvasReplica.tsx @@ -53,7 +53,7 @@ type ActivePanel = | "account" | null; -type ActiveStarterScene = "character-three-view" | null; +type ActiveStarterScene = "story-script" | "character-three-view" | "first-frame" | "audio-to-video" | null; type SceneToolbarMenu = "panorama" | "orbit" | "lighting" | "grid" | "hd" | "crop" | null; type ComposerMenu = | "style" @@ -212,6 +212,45 @@ const CHARACTER_IMAGE_URL = "https://liblibai-online.liblib.cloud/web/ea95cb51f3d94addbb92dc003cd33b49/cca9e085-dccc-4f72-aef7-d68dc6688bcf.png"; const CHARACTER_THREE_VIEW_URL = "https://liblibai-online.liblib.cloud/web/ea95cb51f3d94addbb92dc003cd33b49/7a32ba0b-7b5b-46b1-a86c-e0904482adf7.png"; +const FIRST_FRAME_IMAGE_URL = + "https://liblibai-online.liblib.cloud/web/28aa80df5944499487381983a8f9bbdd/da241fab-3569-49aa-ae4e-c20de9f718e0.png"; +const AUDIO_SOURCE_URL = + "https://liblibai-online.liblib.cloud/web/28aa80df5944499487381983a8f9bbdd/3ca0886d-d35f-4048-95bf-cc655e9c57fd.mp3"; +const AUDIO_REFERENCE_IMAGE_URL = + "https://liblibai-online.liblib.cloud/web/ea95cb51f3d94addbb92dc003cd33b49/1342d344-2d95-41a1-a2aa-4d20869a318c.png"; +const STORY_SCRIPT_PROMPT = "根据我上传的剧本生成一个完整的故事脚本"; +const AUDIO_TO_VIDEO_PROMPT = + "根据上传的音频生成对应场景画面,镜头语言、节奏、音乐匹配情绪变化,电影级质感。"; +const STORY_SCRIPT_TEXT = `《我在盛唐写天下》 + +类型:古风 / 穿越 / 爽文漫剧 +时长建议:60-90秒 +基调:热血 x 盛唐史诗感 x 爽点节奏 + +【序幕】 +【现代 · 深夜办公室】 +键盘声急促。电脑屏幕蓝光刺眼。沈昭昭(女,28岁),面色苍白,伏案加班。手机提示音不断。她抬头,视线模糊,黑屏。 + +【第一幕】 +【盛唐 · 金銮殿 · 日】 +鼓声震天。沈昭昭猛然睁眼,已跪在大殿中央,身着男装官服,双手被押。百官列立,殿宇巍峨。 +大臣厉声:“大逆不道!假称诗才惊世,欺君罔上,当斩!” +沈昭昭震惊低语:“这是……唐朝?” +龙椅之上,皇帝目光沉沉。 +皇帝:“既言才华盖世,当殿作诗。若不能,斩。” +刀光映入她瞳孔。大殿死寂。 + +【第二幕】 +沈昭昭缓缓起身。呼吸渐稳。她望向殿外,长安城阳光万里。 +她低声:“既来盛唐……便与盛唐争一争。” +抬头,高声吟诵:“君不见黄河之水天上来。” +声音回荡大殿。群臣震动。皇帝缓缓站起。诗声激昂,如惊雷落殿。 + +【第三幕】 +殿外风起。长安街市灯火连绵。 +皇帝低声:“此诗,当传万世。” +沈昭昭目光坚定。她轻声自语:“既然来了……那便写尽三万里长安。” +镜头推远。盛唐山河展开。`; function normalizeCanvasTitle(title?: string | null) { const value = String(title || "").trim(); @@ -610,12 +649,19 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib const createStarter = useCallback( (starter: (typeof STARTER_CARDS)[number]) => { - if (starter.title === "角色三视图") { + const starterScenes: Record> = { + 故事脚本生成: "story-script", + 角色三视图: "character-three-view", + 首帧图生视频: "first-frame", + 音频生视频: "audio-to-video", + }; + const starterScene = starterScenes[starter.title]; + if (starterScene) { setNodes([]); setEdges([]); setSelectedNodeId(null); setActivePanel(null); - setActiveStarterScene("character-three-view"); + setActiveStarterScene(starterScene); return; } @@ -752,7 +798,10 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib ))} + {activeStarterScene === "story-script" ? : null} {activeStarterScene === "character-three-view" ? : null} + {activeStarterScene === "first-frame" ? : null} + {activeStarterScene === "audio-to-video" ? : null} {nodes.length === 0 && !activePanel && !activeStarterScene ? (
@@ -855,7 +904,7 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib {activePanel === "assets" ? ( setActivePanel(null)} title="素材库"> - + ) : null} @@ -905,26 +954,13 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib {activePanel === "support" ? ( setActivePanel(null)} title="支持中心"> - + ) : null} {activePanel === "skills" ? ( setActivePanel(null)} title="LibTV Skills"> -
- -
- {Object.entries(capturedCounts.byType || {}).map(([type, count]) => { - const meta = TOOL_TYPE_META[type] || TOOL_TYPE_META.video; - return ( -
-
{String(count)}
-
{meta.label}
-
- ); - })} -
-
+
) : null} @@ -966,19 +1002,19 @@ export function LiblibVideoCanvasReplica({ canvasId, isLoading = false }: Liblib {activePanel === "member" ? ( setActivePanel(null)} title="会员中心"> - + ) : null} {activePanel === "notifications" ? ( setActivePanel(null)} title="通知"> - + ) : null} {activePanel === "account" ? ( setActivePanel(null)} title="账号"> - + ) : null} @@ -1362,6 +1398,328 @@ function MagnetGlyph() { ); } +function StoryScriptScene() { + return ( +
+ +
+ + + +
+ +
+ ); +} + +function FirstFrameVideoScene() { + return ( +
+ +
+ + + +
+ +
+ ); +} + +function AudioToVideoScene() { + return ( +
+ +
+
+ + +
+ + +
+ +
+ ); +} + +function PresetFloatingToolbar({ items }: { items: Array<[string, string]> }) { + return ( +
+ {items.map(([label, message]) => ( + + ))} +
+ ); +} + +function SceneConnector({ className }: { className?: string }) { + return ( +
+
+ +
+ ); +} + +function StoryTextPanel() { + return ( +
+
+ + 剧本 +
+
+
+ 输入内容 + +
+
+ {STORY_SCRIPT_TEXT} +
+
+
+ ); +} + +function ScriptGeneratorPanel() { + const rows = [ + ["01", "现代办公室", "深夜加班,键盘声急促,人物体力透支", "环境键盘声"], + ["02", "盛唐大殿", "女主惊醒跪于金銮殿,百官压迫", "鼓声与低频"], + ["03", "长安街市", "诗声落下,盛唐山河展开", "史诗音乐起"], + ]; + return ( +
+
+ + 脚本生成器 +
+
+
+ 故事脚本 + 待生成 +
+
+ {["镜号", "场景", "画面", "声音"].map((item) => ( +
{item}
+ ))} +
+ {rows.map((row) => ( +
+ {row.map((cell) => ( +
{cell}
+ ))} +
+ ))} + +
+
+ ); +} + +function PresetMediaPanel({ + imageUrl, + label, + small = false, + wide = false, +}: { + imageUrl: string; + label: string; + small?: boolean; + wide?: boolean; +}) { + return ( +
+
+ + {label} +
+
+ {label} + +
+
+ ); +} + +function VideoResultPanel({ label }: { label: string }) { + return ( +
+
+
+
+
+
+
+
+
待生成视频
+
生成后将在这里预览
+
+ +
+
+ ); +} + +function AudioResourcePanel() { + return ( +
+
+ + 音频 +
+
+
+ +
+
情绪配乐.mp3
+
音频生视频参考素材
+
+ + 试听 + +
+
+ {Array.from({ length: 38 }).map((_, index) => ( + + ))} +
+
+
+ ); +} + +function PresetComposerPanel({ + credit, + prompt, + submitMessage, + thumbnailUrl, + title, +}: { + credit: string; + prompt: string; + submitMessage: string; + thumbnailUrl?: string; + title: string; +}) { + return ( +
+ +
+ {title} + {thumbnailUrl ? ( +
+ +
+ ) : null} +
+
{prompt}
+
+ toast.info("模型选择接口待接入。")} /> + toast.info("比例选择接口待接入。")} /> + toast.info("清晰度选择接口待接入。")} /> + toast.info("镜头配置接口待接入。")} /> + toast.info("生成数量接口待接入。")} /> + toast.info("积分估算接口待接入。")} /> + +
+
+ ); +} + function CharacterThreeViewScene() { const [toolbarMenu, setToolbarMenu] = useState(null); @@ -2171,6 +2529,207 @@ function ToggleRow({ ); } +function AssetLibraryPanel() { + const assets = [ + { label: "角色图", type: "图片", url: CHARACTER_IMAGE_URL }, + { label: "角色三视图", type: "图片", url: CHARACTER_THREE_VIEW_URL }, + { label: "首帧", type: "图片", url: FIRST_FRAME_IMAGE_URL }, + { label: "音频参考图", type: "图片", url: AUDIO_REFERENCE_IMAGE_URL }, + ]; + return ( +
+
+ {["项目素材", "图片", "视频", "音频", "风格", "标记"].map((item, index) => ( + + ))} +
+ +
+ {assets.map((asset) => ( + + ))} +
+
+ ); +} + +function SkillsAccessPanel() { + return ( +
+
+
+
+
OpenAPI Access Key
+
用于 LibTV Skills 调用、模型能力和自动化任务。
+
+ +
+
+ 暂无 Access Key +
+
+
+ {Object.entries(capturedCounts.byType || {}).map(([type, count]) => { + const meta = TOOL_TYPE_META[type] || TOOL_TYPE_META.video; + return ( +
+
{String(count)}
+
{meta.label}
+
+ ); + })} +
+
+ ); +} + +function MemberCenterPanel() { + return ( +
+
+
限时 39 折
+
会员特惠39折
+
会员超市、模型权益、生成额度与积分套餐待接入。
+ +
+
+ {[ + ["100", "可用积分"], + ["67", "模型能力"], + ["25", "工作流预设"], + ].map(([value, label]) => ( +
+
{value}
+
{label}
+
+ ))} +
+
+ ); +} + +function NotificationsPanel() { + return ( +
+ {["全部", "生成任务", "系统通知", "会员活动"].map((item, index) => ( + + ))} + {[ + ["生成任务", "任务状态、进度轮询和失败原因接口待接入。"], + ["系统通知", "审核、账户和平台消息接口待接入。"], + ["会员活动", "会员超市与活动消息接口待接入。"], + ].map(([title, description]) => ( +
+
{title}
+
{description}
+
+ ))} +
+ ); +} + +function AccountPanel() { + return ( +
+
+ avatar +
+
微信用户82a0d8
+
账号中心、团队空间和额度设置待接入。
+
+ +
+
+ {[ + ["100", "当前积分"], + ["个人空间", "当前空间"], + ].map(([value, label]) => ( +
+
{value}
+
{label}
+
+ ))} +
+
+ ); +} + +function SupportPanel() { + return ( +
+ {[ + ["使用教程", "打开 LibTV 视频画布教程。"], + ["联系客服", "提交工单或联系在线客服。"], + ["问题反馈", "反馈画布、生成和支付问题。"], + ].map(([title, description]) => ( + + ))} +
+ ); +} + function LibModal({ children, onClose,