Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -679,13 +679,13 @@ def get_demo_path(filename):
|
|
| 679 |
# ]],
|
| 680 |
# inputs=llm_input
|
| 681 |
# )
|
|
|
|
| 682 |
with gr.Blocks(title="AI 剧本视频工厂") as demo:
|
| 683 |
gr.Markdown("# 🎬 ScriptAgent & Sora/Veo 视频生成工坊 ")
|
| 684 |
|
| 685 |
-
|
| 686 |
-
with gr.Tabs(elem_id="main_tabs") as tabs:
|
| 687 |
# --- TAB 1: 剧本创作 ---
|
| 688 |
-
with gr.Tab("📝 第一步:剧本创作"
|
| 689 |
with gr.Row():
|
| 690 |
with gr.Column():
|
| 691 |
llm_input = gr.Textbox(
|
|
@@ -701,7 +701,14 @@ with gr.Blocks(title="AI 剧本视频工厂") as demo:
|
|
| 701 |
lines=10,
|
| 702 |
interactive=True
|
| 703 |
)
|
| 704 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 705 |
|
| 706 |
gr.Examples(
|
| 707 |
[[
|
|
@@ -712,7 +719,7 @@ with gr.Blocks(title="AI 剧本视频工厂") as demo:
|
|
| 712 |
inputs=llm_input
|
| 713 |
)
|
| 714 |
|
| 715 |
-
#
|
| 716 |
gr.Markdown("---")
|
| 717 |
with gr.Accordion("💻 本地部署完整代码(点击展开查看)", open=False):
|
| 718 |
gr.Markdown("""
|
|
@@ -733,13 +740,13 @@ print("下载模型所有文件...")
|
|
| 733 |
snapshot_download(
|
| 734 |
repo_id=model_name,
|
| 735 |
local_dir=local_path,
|
| 736 |
-
local_dir_use_symlinks=False,
|
| 737 |
-
resume_download=True
|
| 738 |
)
|
| 739 |
|
| 740 |
print(f"模型已完整下载到: {local_path}")
|
| 741 |
|
| 742 |
-
#
|
| 743 |
from swift.llm import PtEngine, RequestConfig, InferRequest
|
| 744 |
|
| 745 |
engine = PtEngine(local_path, max_batch_size=1)
|
|
@@ -780,7 +787,19 @@ print(response.choices[0].message.content)'''
|
|
| 780 |
""")
|
| 781 |
|
| 782 |
# --- TAB 2: 视频生成 ---
|
| 783 |
-
with gr.Tab("🎥 第二步:视频生成"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 784 |
with gr.Row():
|
| 785 |
# 左侧配置区
|
| 786 |
with gr.Column(scale=1):
|
|
@@ -822,7 +841,8 @@ print(response.choices[0].message.content)'''
|
|
| 822 |
video_script_input = gr.TextArea(
|
| 823 |
label="分镜脚本",
|
| 824 |
lines=8,
|
| 825 |
-
placeholder="1. [0-8秒] ..."
|
|
|
|
| 826 |
)
|
| 827 |
gen_btn = gr.Button("🚀 开始生成", variant="primary")
|
| 828 |
status_log = gr.Textbox(label="日志", interactive=False)
|
|
@@ -843,7 +863,6 @@ print(response.choices[0].message.content)'''
|
|
| 843 |
gr.Markdown("---")
|
| 844 |
gr.Markdown("### 🌟 精选成片案例 (Demo Showcase)")
|
| 845 |
|
| 846 |
-
# 使用 2x2 布局
|
| 847 |
for i in range(0, 4, 2):
|
| 848 |
with gr.Row():
|
| 849 |
for j in range(2):
|
|
@@ -862,26 +881,46 @@ print(response.choices[0].message.content)'''
|
|
| 862 |
interactive=False
|
| 863 |
)
|
| 864 |
|
| 865 |
-
#
|
| 866 |
gr.HTML('<p style="color: red; font-weight: bold; text-align: center; margin-top: 20px; font-size: 16px;">⚠️ 注意:仅供简单测试,由于成本问题在线平台内存只有18G,我们量化了模型,性能效果并不能保证,如果需要最准确的输出请自行部署即可</p>')
|
| 867 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 868 |
# --- 逻辑绑定 ---
|
| 869 |
llm_btn.click(chat_with_scriptagent, llm_input, llm_output)
|
| 870 |
|
| 871 |
-
# 🔥
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 872 |
to_video_btn.click(
|
| 873 |
-
fn=
|
| 874 |
inputs=llm_output,
|
| 875 |
-
outputs=video_script_input,
|
| 876 |
-
_js="""
|
| 877 |
-
() => {
|
| 878 |
-
// 查找第二个标签页按钮并点击
|
| 879 |
-
const tabs = document.querySelectorAll('#main_tabs button[role="tab"]');
|
| 880 |
-
if (tabs && tabs.length > 1) {
|
| 881 |
-
tabs[1].click(); // 点击第二个标签页
|
| 882 |
-
}
|
| 883 |
-
}
|
| 884 |
-
"""
|
| 885 |
)
|
| 886 |
|
| 887 |
model_sel.change(
|
|
|
|
| 679 |
# ]],
|
| 680 |
# inputs=llm_input
|
| 681 |
# )
|
| 682 |
+
|
| 683 |
with gr.Blocks(title="AI 剧本视频工厂") as demo:
|
| 684 |
gr.Markdown("# 🎬 ScriptAgent & Sora/Veo 视频生成工坊 ")
|
| 685 |
|
| 686 |
+
with gr.Tabs():
|
|
|
|
| 687 |
# --- TAB 1: 剧本创作 ---
|
| 688 |
+
with gr.Tab("📝 第一步:剧本创作"):
|
| 689 |
with gr.Row():
|
| 690 |
with gr.Column():
|
| 691 |
llm_input = gr.Textbox(
|
|
|
|
| 701 |
lines=10,
|
| 702 |
interactive=True
|
| 703 |
)
|
| 704 |
+
# 🔥 修改:添加提示信息组件
|
| 705 |
+
copy_status = gr.Textbox(
|
| 706 |
+
label="",
|
| 707 |
+
value="",
|
| 708 |
+
visible=False,
|
| 709 |
+
elem_classes="copy-status"
|
| 710 |
+
)
|
| 711 |
+
to_video_btn = gr.Button("⬇️ 复制到视频生成", variant="secondary")
|
| 712 |
|
| 713 |
gr.Examples(
|
| 714 |
[[
|
|
|
|
| 719 |
inputs=llm_input
|
| 720 |
)
|
| 721 |
|
| 722 |
+
# 本地部署代码展示区(保持不变)
|
| 723 |
gr.Markdown("---")
|
| 724 |
with gr.Accordion("💻 本地部署完整代码(点击展开查看)", open=False):
|
| 725 |
gr.Markdown("""
|
|
|
|
| 740 |
snapshot_download(
|
| 741 |
repo_id=model_name,
|
| 742 |
local_dir=local_path,
|
| 743 |
+
local_dir_use_symlinks=False,
|
| 744 |
+
resume_download=True
|
| 745 |
)
|
| 746 |
|
| 747 |
print(f"模型已完整下载到: {local_path}")
|
| 748 |
|
| 749 |
+
# 使用 SWIFT 加载
|
| 750 |
from swift.llm import PtEngine, RequestConfig, InferRequest
|
| 751 |
|
| 752 |
engine = PtEngine(local_path, max_batch_size=1)
|
|
|
|
| 787 |
""")
|
| 788 |
|
| 789 |
# --- TAB 2: 视频生成 ---
|
| 790 |
+
with gr.Tab("🎥 第二步:视频生成"):
|
| 791 |
+
# 🔥 新增:顶部提示区域
|
| 792 |
+
gr.Markdown("""
|
| 793 |
+
<div style="background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
|
| 794 |
+
padding: 15px;
|
| 795 |
+
border-radius: 10px;
|
| 796 |
+
color: white;
|
| 797 |
+
text-align: center;
|
| 798 |
+
margin-bottom: 20px;">
|
| 799 |
+
💡 <b>提示</b>:在「第一步:剧本创作」中点击「⬇️ 复制到视频生成」后,剧本会自动填充到下方「分镜脚本」输入框
|
| 800 |
+
</div>
|
| 801 |
+
""")
|
| 802 |
+
|
| 803 |
with gr.Row():
|
| 804 |
# 左侧配置区
|
| 805 |
with gr.Column(scale=1):
|
|
|
|
| 841 |
video_script_input = gr.TextArea(
|
| 842 |
label="分镜脚本",
|
| 843 |
lines=8,
|
| 844 |
+
placeholder="1. [0-8秒] ...",
|
| 845 |
+
elem_classes="script-input" # 🔥 添加样式类
|
| 846 |
)
|
| 847 |
gen_btn = gr.Button("🚀 开始生成", variant="primary")
|
| 848 |
status_log = gr.Textbox(label="日志", interactive=False)
|
|
|
|
| 863 |
gr.Markdown("---")
|
| 864 |
gr.Markdown("### 🌟 精选成片案例 (Demo Showcase)")
|
| 865 |
|
|
|
|
| 866 |
for i in range(0, 4, 2):
|
| 867 |
with gr.Row():
|
| 868 |
for j in range(2):
|
|
|
|
| 881 |
interactive=False
|
| 882 |
)
|
| 883 |
|
| 884 |
+
# 页面底部警告
|
| 885 |
gr.HTML('<p style="color: red; font-weight: bold; text-align: center; margin-top: 20px; font-size: 16px;">⚠️ 注意:仅供简单测试,由于成本问题在线平台内存只有18G,我们量化了模型,性能效果并不能保证,如果需要最准确的输出请自行部署即可</p>')
|
| 886 |
|
| 887 |
+
# 🔥 添加自定义 CSS 实现高亮动画
|
| 888 |
+
demo.load(
|
| 889 |
+
None,
|
| 890 |
+
None,
|
| 891 |
+
None,
|
| 892 |
+
js="""
|
| 893 |
+
function() {
|
| 894 |
+
const style = document.createElement('style');
|
| 895 |
+
style.textContent = `
|
| 896 |
+
@keyframes highlight {
|
| 897 |
+
0%, 100% { background-color: transparent; }
|
| 898 |
+
50% { background-color: rgba(102, 126, 234, 0.2); }
|
| 899 |
+
}
|
| 900 |
+
.script-input.highlight {
|
| 901 |
+
animation: highlight 1.5s ease-in-out 3;
|
| 902 |
+
border: 2px solid #667eea !important;
|
| 903 |
+
}
|
| 904 |
+
`;
|
| 905 |
+
document.head.appendChild(style);
|
| 906 |
+
}
|
| 907 |
+
"""
|
| 908 |
+
)
|
| 909 |
+
|
| 910 |
# --- 逻辑绑定 ---
|
| 911 |
llm_btn.click(chat_with_scriptagent, llm_input, llm_output)
|
| 912 |
|
| 913 |
+
# 🔥 修改后的按钮逻辑:复制文本 + 显示成功提示
|
| 914 |
+
def copy_to_video(script_text):
|
| 915 |
+
"""复制剧本到视频生成标签页"""
|
| 916 |
+
if not script_text or not script_text.strip():
|
| 917 |
+
return script_text, gr.update(value="⚠️ 剧本为空,无法复制", visible=True)
|
| 918 |
+
return script_text, gr.update(value="✅ 已复制到「第二步:视频生成」→「分镜脚本」,请切换标签页查看", visible=True)
|
| 919 |
+
|
| 920 |
to_video_btn.click(
|
| 921 |
+
fn=copy_to_video,
|
| 922 |
inputs=llm_output,
|
| 923 |
+
outputs=[video_script_input, copy_status]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 924 |
)
|
| 925 |
|
| 926 |
model_sel.change(
|