Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -85,7 +85,7 @@ DEMO_DATA = [
|
|
| 85 |
{
|
| 86 |
"file": "demo1.mp4",
|
| 87 |
"title": "案例 1",
|
| 88 |
-
"script": "
|
| 89 |
},
|
| 90 |
{
|
| 91 |
"file": "demo2.mp4",
|
|
@@ -95,7 +95,7 @@ DEMO_DATA = [
|
|
| 95 |
{
|
| 96 |
"file": "demo3.mp4",
|
| 97 |
"title": "案例 3",
|
| 98 |
-
"script": "
|
| 99 |
},
|
| 100 |
{
|
| 101 |
"file": "demo4.mp4",
|
|
@@ -378,7 +378,7 @@ def parse_script_nodes(script_text: str) -> List[str]:
|
|
| 378 |
|
| 379 |
|
| 380 |
def extract_last_frame(video_path: str, output_path: str) -> Optional[str]:
|
| 381 |
-
"""提取视频最后一帧作为参考图"""
|
| 382 |
if cv2 is None:
|
| 383 |
return None
|
| 384 |
|
|
@@ -594,9 +594,10 @@ def get_demo_path(filename):
|
|
| 594 |
with gr.Blocks(title="AI 剧本视频工厂") as demo:
|
| 595 |
gr.Markdown("# 🎬 ScriptAgent & Sora/Veo 视频生成工坊 ")
|
| 596 |
|
| 597 |
-
|
|
|
|
| 598 |
# --- TAB 1: 剧本创作 ---
|
| 599 |
-
with gr.Tab("📝 第一步:剧本创作"):
|
| 600 |
with gr.Row():
|
| 601 |
with gr.Column():
|
| 602 |
llm_input = gr.Textbox(
|
|
@@ -628,7 +629,7 @@ with gr.Blocks(title="AI 剧本视频工厂") as demo:
|
|
| 628 |
with gr.Accordion("💻 本地部署完整代码(点击展开查看)", open=False):
|
| 629 |
gr.Markdown("""
|
| 630 |
### 📦 完整部署步骤
|
| 631 |
-
|
| 632 |
""")
|
| 633 |
|
| 634 |
deployment_code = '''import os
|
|
@@ -682,15 +683,10 @@ print(response.choices[0].message.content)'''
|
|
| 682 |
- 显存: 16GB+ (推荐 24GB)
|
| 683 |
- 内存: 32GB+
|
| 684 |
```
|
| 685 |
-
|
| 686 |
-
### ⚡ 本地部署优势
|
| 687 |
-
- ✅ 完整精度模型,无量化损失
|
| 688 |
-
- ✅ 更快的推理速度
|
| 689 |
-
- ✅ 无网络限制,支持离线运行
|
| 690 |
-
- ✅ 可自定义参数(temperature, max_tokens等)
|
| 691 |
""")
|
|
|
|
| 692 |
# --- TAB 2: 视频生成 ---
|
| 693 |
-
with gr.Tab("🎥 第二步:视频生成"):
|
| 694 |
with gr.Row():
|
| 695 |
# 左侧配置区
|
| 696 |
with gr.Column(scale=1):
|
|
@@ -772,18 +768,19 @@ print(response.choices[0].message.content)'''
|
|
| 772 |
lines=6,
|
| 773 |
max_lines=6,
|
| 774 |
interactive=False
|
| 775 |
-
|
| 776 |
)
|
|
|
|
| 777 |
# 🔥 页面底部警告提示(标红显示)
|
| 778 |
gr.HTML('<p style="color: red; font-weight: bold; text-align: center; margin-top: 20px; font-size: 16px;">⚠️ 注意:仅供简单测试,由于成本问题在线平台内存只有18G,我们量化了模型,性能效果并不能保证,如果需要最准确的输出请自行部署即可</p>')
|
| 779 |
|
| 780 |
# --- 逻辑绑定 ---
|
| 781 |
llm_btn.click(chat_with_scriptagent, llm_input, llm_output)
|
| 782 |
|
|
|
|
| 783 |
to_video_btn.click(
|
| 784 |
-
lambda x: (x,
|
| 785 |
inputs=llm_output,
|
| 786 |
-
outputs=[video_script_input,
|
| 787 |
)
|
| 788 |
|
| 789 |
model_sel.change(
|
|
|
|
| 85 |
{
|
| 86 |
"file": "demo1.mp4",
|
| 87 |
"title": "案例 1",
|
| 88 |
+
"script": "[Dialogue]: 1. [0-9 seconds] (Camera movement: Handheld + long shot - medium close-up - long shot) In a forest clearing, Su Luo paces anxiously, the protagonist stands still; a medium close-up shot with a camera in hand, Su Luo scratches his hair and kicks a stone: "I really shouldn't have agreed to Qin Fei, how can I find all three time boxes in such a short time!" He stomps his foot, then cuts back to a long shot. 2. [9-18 seconds] (Shallow depth of field + long shot - medium shot - long shot) The protagonist approaches, a medium shot over the shoulder in out of focus asks: "What is a time box?" Su Luo turns around and professionally gestures: "A cloud silk control group countdown mechanism box." The two stand facing each other in a long shot. 3. [18-26 seconds] (Tilt + long shot - close-up - long shot) The long shot continues, then a close-up shot of Su Luo in a scholarly manner: "It can only be opened at a specified time, so it's called a time box." The camera pans down to the gesture and then back to the face, then the long shot ends. 4. [26-36 seconds] (Arc + long shot - medium close-up - long shot) Su Luo exaggerates in the long shot, surrounded by a medium close-up: "Qin Fei buried three boxes saying he couldn't find them, I patted my chest on the spot: Su Luo, the expert in local customs, will get them all done in an hour!" Chin raised, chest patted, still proud in the long shot. 5. [36-44 seconds] (Shaky + long shot - medium shot - long shot) The protagonist in the medium shot teases: "Seeing how anxious you are, you haven't finished, have you?" Su Luo in the background instantly deflates, shoulders droop, slightly swaying to indicate guilt, long shot lowers head. 6. [44-53 seconds] (Pan + long shot - close-up - long shot) Long shot lowers head, close-up Su Luo rubs the corner of his clothes and whispers: "Who would have thought he would cheat with the boxes... help me?" He looks up and moves to make eye contact, long shot meets eyes. 7. [53-62 seconds] (Crash Zoom + Long Shot - Medium Shot - Long Shot) The protagonist nods and smiles in the long shot, then a quick push to the medium shot closes up. Su Luo exclaims with delight, "Great! I'll leave those two directions to you, I'll handle the rest!" She pounds her chest and points into the distance, the protagonist in the long shot exhaling and setting off. 【Character Design】 Su Luo: Medium height and light build, large eyes, flaxen brown hair, messy ponytail, short jacket, tools, belt, emotions instantly revealed. Protagonist: Medium height and upright, soft dark hair, simple dark-colored clothing, reserved and calm, nodding slightly. 【Scene】Afternoon dappled sunlight in a forest clearing, pebbles, fallen leaves, quiet trees, transitioning from anxiety to relaxed cooperation. 【Positioning】 1. Su Luo walks back and forth in the center of the clearing, the protagonist at the edge, at a distance. 2. The protagonist takes two or three steps closer to face her. 3-5. Maintaining close distance, Su Luo faces the protagonist/turns sideways and lowers her head. 6. They look at each other again. 7. Su Luo points to the distance."
|
| 89 |
},
|
| 90 |
{
|
| 91 |
"file": "demo2.mp4",
|
|
|
|
| 95 |
{
|
| 96 |
"file": "demo3.mp4",
|
| 97 |
"title": "案例 3",
|
| 98 |
+
"script": "【Dialogue】: 1. [0-9 seconds] (Handheld Camera Effect + panoramic shot, medium close-up shot) A long shot shows the desolate scene after the fierce battle. The protagonist and Meng Ya stand on the right side of the screen, their postures wary; on the left side of the screen, Yuan Xue and Zhao Dongxu lean against a burning wooden stake, panting weakly. The camera moves forward and focuses on Yuan Xue, who is trembling and looking at the protagonist with fear on her face. Her voice trembles: "Thank you so much! Luckily you arrived in time! Otherwise, we would have become a barbecue feast by now..." She finishes speaking and gasps for breath. The camera moves to the protagonist's face. He frowns slightly, his gaze shifts from Yuan Xue to Zhao Dongxu, and asks with concern and professional assessment: "How badly are you injured? Can you still stand up?" The last second returns to the long shot, confirming the four people's positions. 2. [9-17 seconds] (Shallow Depth of Field + panoramic shot, medium shot) In the long shot, Zhao Dongxu maintains a crouching posture. The camera cuts to a medium shot focusing on Zhao Dongxu, blurring the background of the protagonist and the distant firelight. Tears stream down Zhao Dongxu's pale face, a result of his pain. He avoids looking directly at the protagonist, instead looking down at his numb legs, stammering, "I can't feel my legs at all..." His voice is filled with despair and helplessness. The final second returns to a long shot, contrasting Zhao Dongxu's despair with the protagonist's seriousness. 3. [17-25 seconds] (Panning Shot + wide shot, medium shot) In the long shot, Meng Ya steps forward from behind the protagonist. The camera focuses on Meng Ya in a medium shot. He has his arms crossed, a serious expression on his face, and says to Zhao Dongxu and Yuan Xue in an unquestionable tone, "If you're not strong enough, don't try to take on a top-tier commission! Come with us, back to the camp to get treatment from Bai Cao's family." After saying that, he turns to the side and gestures with his chin towards the protagonist. The camera then pans across the protagonist, who is also on guard. Meng Ya continues, "What's wrong with you? Why are you spacing out?" In the last second, the camera returns to a wide shot, showing Meng Ya standing in the middle of the path leading to the protagonist. 4. [25-34 seconds] (Arc Shot + wide shot, close-up shot) In the wide shot, the protagonist ignores Meng Ya and stares ahead. The camera moves slowly in an arc around the protagonist, then zooms in on his face for a close-up. His eyes are sharp and focused, his brow furrowed as he nods and examines his surroundings: “Something’s not right here.” He first senses the temperature of the air, then looks at the remnants of the extinguished flames on the ground. “The temperature is still high, and the flames haven’t died down… Could there be any survivors?” The final second returns to a wide shot, showing the protagonist standing alone at the front of the group, forming a silhouette. 5. [34-41 seconds] (Crash Zoom + wide shot, extreme close-up) In a wide shot, the protagonist’s gaze abruptly shifts to a diagonal angle ahead. Plot: The silhouette of a small aircraft suddenly sweeps past the wreckage. The camera zooms in on the protagonist for an extreme close-up, capturing the violent contraction of his pupils. He gasps, realizing: “And… I’m worried there are still students trapped ahead.” His eyes change from shock to determination. The final second returns to a wide shot, showing the protagonist now fully turned towards the road ahead, taking a step forward without hesitation. 6. [41-49 seconds] (Deep Depth of Field + panoramic shot, medium-long shot) In the long shot, the protagonist walks forward, and Meng Ya stops. The shot switches to a medium-long shot, the depth of field widens, and the foreground shows Meng Ya's back as he turns away. He decisively waves to the protagonist's back and says loudly, "Understood. Let's split up then. I'll escort the wounded to the camp first, and I'll come back to find you later." His walking figure is still clear in the depth of field, showing his determination to do as he says. In the last second, the shot returns to a long shot, and Meng Ya has already walked some distance. 7. [49-57 seconds] (Whip Pan + panoramic shot, medium-long shot) In the long shot, Meng Ya stops after taking a few steps. The camera begins from a distance, slightly behind Meng Ya. He's about to turn around, but gestures with his eyes to the protagonist in front of him. Turning back again, his voice tinged with concern, he says, "Hey, don't go too far! Big Eye Owl will contact you later!" Before he finishes speaking, the camera abruptly pans from his face to the protagonist standing motionless a few steps behind him. The final second returns to a wide shot, showing the two figures, one in front of the other, maintaining a distance suitable for communication, forming the frame. [Character Description]: Yuan Xue: Approximately 165cm tall/slender build/pale, sweaty, and fearful facial features/long, dark hair disheveled/wearing simple, light-colored clothing soaked in sweat/a timid and helpless demeanor, her body language showing trembling and an inability to look directly at others. Main Character: Approximately 180cm tall / Well-proportioned and agile / Distinct facial features, often with a furrowed brow / Short, dark hair, clean and neat / Wears dark tactical uniform, durable and easy to move in / Calm, sharp, and professional demeanor, habitually vigilant, his habitual action of nodding in scrutiny when observing his environment. Meng Ya: Approximately 182cm tall / Sturdy build, confident stance / Strong facial features, serious expression, sharp eyes / Short, spiky black hair / Wears heavily armored combat uniform with numbers, appearing experienced / Demeanor of a young commander, decisive in action, direct in speech, habitually using gestures such as crossing his arms and gesturing with his chin to express his attitude. [Scene Description]: A desolate battlefield wreckage under a clear afternoon sky, the air hot and dry, traces of recently extinguished flames on the ground, scattered burning logs emitting an apocalyptic glow. [Positioning]: 1: The main character and Meng Ya are on the right side of the screen, Yuan Xue and Zhao Dongxu are on the left, slightly behind, leaning against the burning logs. 2. Zhao Dongxu remains crouched on the left, with the protagonist and Meng Ya behind him, remaining alert.3. Meng Ya steps forward from behind the protagonist, standing between the protagonist and Zhao Dongxu, turning sideways towards the protagonist.4. The protagonist stands alone at the front of the group, facing forward; Meng Ya, Yuan Xue, and Zhao Dongxu are behind him.5. The protagonist, who was facing forward, suddenly turns to face diagonally forward.6. The protagonist walks forward, while Meng Ya stops, turns his back to the protagonist, and walks in the opposite direction.7. Meng Ya is in front, and the protagonist is behind, maintaining a distance of several steps, forming a front-and-back formation."
|
| 99 |
},
|
| 100 |
{
|
| 101 |
"file": "demo4.mp4",
|
|
|
|
| 378 |
|
| 379 |
|
| 380 |
def extract_last_frame(video_path: str, output_path: str) -> Optional[str]:
|
| 381 |
+
"""提取视频最后一帧作为参考图"""
|
| 382 |
if cv2 is None:
|
| 383 |
return None
|
| 384 |
|
|
|
|
| 594 |
with gr.Blocks(title="AI 剧本视频工厂") as demo:
|
| 595 |
gr.Markdown("# 🎬 ScriptAgent & Sora/Veo 视频生成工坊 ")
|
| 596 |
|
| 597 |
+
# 🔥 关键修改:给 Tabs 组件添加变量引用
|
| 598 |
+
with gr.Tabs() as tabs:
|
| 599 |
# --- TAB 1: 剧本创作 ---
|
| 600 |
+
with gr.Tab("📝 第一步:剧本创作", id=0):
|
| 601 |
with gr.Row():
|
| 602 |
with gr.Column():
|
| 603 |
llm_input = gr.Textbox(
|
|
|
|
| 629 |
with gr.Accordion("💻 本地部署完整代码(点击展开查看)", open=False):
|
| 630 |
gr.Markdown("""
|
| 631 |
### 📦 完整部署步骤
|
| 632 |
+
以下代码可在本地完整运行,获得最佳性能和输出质量:
|
| 633 |
""")
|
| 634 |
|
| 635 |
deployment_code = '''import os
|
|
|
|
| 683 |
- 显存: 16GB+ (推荐 24GB)
|
| 684 |
- 内存: 32GB+
|
| 685 |
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 686 |
""")
|
| 687 |
+
|
| 688 |
# --- TAB 2: 视频生成 ---
|
| 689 |
+
with gr.Tab("🎥 第二步:视频生成", id=1):
|
| 690 |
with gr.Row():
|
| 691 |
# 左侧配置区
|
| 692 |
with gr.Column(scale=1):
|
|
|
|
| 768 |
lines=6,
|
| 769 |
max_lines=6,
|
| 770 |
interactive=False
|
|
|
|
| 771 |
)
|
| 772 |
+
|
| 773 |
# 🔥 页面底部警告提示(标红显示)
|
| 774 |
gr.HTML('<p style="color: red; font-weight: bold; text-align: center; margin-top: 20px; font-size: 16px;">⚠️ 注意:仅供简单测试,由于成本问题在线平台内存只有18G,我们量化了模型,性能效果并不能保证,如果需要最准确的输出请自行部署即可</p>')
|
| 775 |
|
| 776 |
# --- 逻辑绑定 ---
|
| 777 |
llm_btn.click(chat_with_scriptagent, llm_input, llm_output)
|
| 778 |
|
| 779 |
+
# 🔥 关键修改:返回 (剧本内容, 标签页索引)
|
| 780 |
to_video_btn.click(
|
| 781 |
+
lambda x: (x, 1), # 1 表示切换到第二个标签页(索引从0开始)
|
| 782 |
inputs=llm_output,
|
| 783 |
+
outputs=[video_script_input, tabs] # 输出到文本框和标签页切换器
|
| 784 |
)
|
| 785 |
|
| 786 |
model_sel.change(
|