| import gradio as gr |
| import os |
| import tempfile |
| import random |
| from datetime import datetime |
| from moviepy.editor import VideoFileClip, concatenate_videoclips, AudioFileClip, vfx |
| from openai import OpenAI |
|
|
| |
| client = OpenAI( |
| api_key=os.getenv("sk-ZYyxdh3NexC863OUdicSlKrunXEPlRlsLBMwc1vXMGEVwZdb") |
| ) |
|
|
| def analyze_video_content(video_path, video_count): |
| """使用 OpenAI 分析视频内容""" |
| try: |
| prompt = f"""作为专业视频内容分析师,请为用户上传的 {video_count} 个视频文件生成详细分析报告。 |
| |
| 分析要点: |
| 1. 📹 视频内容推测(基于用户上传行为) |
| 2. 🎵 推荐的背景音乐风格和节奏 |
| 3. ✂️ 最佳剪辑策略和转场效果 |
| 4. 🎯 目标受众和传播渠道建议 |
| 5. 📈 内容优化和提升建议 |
| |
| 请用中文回答,格式清晰,每个要点用emoji标识。""" |
|
|
| response = client.chat.completions.create( |
| model="gpt-4o-mini", |
| messages=[ |
| { |
| "role": "system", |
| "content": "你是一位资深的视频内容策划和分析专家,擅长为创作者提供专业的视频制作建议。" |
| }, |
| { |
| "role": "user", |
| "content": prompt |
| } |
| ], |
| max_tokens=600, |
| temperature=0.7 |
| ) |
| |
| return response.choices[0].message.content |
| except Exception as e: |
| return f"❌ AI 分析失败: {str(e)}\n💡 请检查 OpenAI API Key 是否正确设置" |
|
|
| def generate_creative_titles(video_count, content_theme="创意混剪"): |
| """使用 OpenAI 生成创意标题""" |
| try: |
| prompt = f"""请为 {video_count} 个{content_theme}视频生成吸引眼球的标题。 |
| |
| 要求: |
| - 🔥 热门关键词和流行元素 |
| - 📱 适合抖音、小红书等平台 |
| - 💯 每个标题15-25字最佳 |
| - 🎭 风格多样化(搞笑、治愈、励志等) |
| - 🚀 包含动作词汇增加点击欲望 |
| |
| 请直接给出 {video_count} 个标题,每行一个,前面加上序号。""" |
|
|
| response = client.chat.completions.create( |
| model="gpt-4o-mini", |
| messages=[ |
| { |
| "role": "system", |
| "content": "你是一位专业的新媒体内容创作者,精通各种平台的标题优化技巧。" |
| }, |
| { |
| "role": "user", |
| "content": prompt |
| } |
| ], |
| max_tokens=400, |
| temperature=0.9 |
| ) |
| |
| return response.choices[0].message.content |
| except Exception as e: |
| return f"❌ 标题生成失败: {str(e)}" |
|
|
| def generate_project_summary(video_count, processing_time): |
| """生成项目处理总结""" |
| try: |
| prompt = f"""请为刚完成的视频混剪项目生成专业总结报告: |
| |
| 项目信息: |
| - 处理视频数量: {video_count} 个 |
| - 处理用时: {processing_time} |
| - 使用技术: MoviePy + OpenAI GPT |
| |
| 请包含: |
| 1. 🎬 项目执行概况 |
| 2. ⚡ 技术亮点和特色 |
| 3. 📊 质量评估和优势 |
| 4. 🔮 后续优化方向 |
| 5. 💼 商业应用价值 |
| |
| 用专业但易懂的语言,中文回答。""" |
|
|
| response = client.chat.completions.create( |
| model="gpt-4o", |
| messages=[ |
| { |
| "role": "system", |
| "content": "你是一位技术项目管理专家,擅长撰写项目总结和技术方案评估报告。" |
| }, |
| { |
| "role": "user", |
| "content": prompt |
| } |
| ], |
| max_tokens=700, |
| temperature=0.6 |
| ) |
| |
| return response.choices[0].message.content |
| except Exception as e: |
| return f"❌ 总结生成失败: {str(e)}" |
|
|
| def get_ai_processing_suggestions(file_count, audio_duration): |
| """获取处理建议""" |
| try: |
| prompt = f"""基于用户上传情况给出处理建议: |
| - 视频文件数: {file_count} |
| - 音频时长: {audio_duration:.1f}秒 |
| |
| 请提供: |
| 1. 最佳切片时长建议 |
| 2. 推荐输出视频数量 |
| 3. 效果和滤镜建议 |
| 4. 注意事项提醒 |
| |
| 简洁回答,3-4条建议即可。""" |
|
|
| response = client.chat.completions.create( |
| model="gpt-4o-mini", |
| messages=[ |
| {"role": "user", "content": prompt} |
| ], |
| max_tokens=300, |
| temperature=0.5 |
| ) |
| |
| return response.choices[0].message.content |
| except Exception as e: |
| return "无法获取AI建议,将使用默认参数处理" |
|
|
| def process_videos_with_openai(video_files, audio_file, clip_duration=2, num_output_videos=3): |
| """集成 OpenAI GPT 的视频处理主函数""" |
| |
| if not video_files or not audio_file: |
| return "❌ 请上传视频文件和音频文件", [], "", "", "" |
| |
| start_time = datetime.now() |
| |
| |
| audio_duration = 0 |
| try: |
| temp_audio = AudioFileClip(audio_file.name) |
| audio_duration = temp_audio.duration |
| temp_audio.close() |
| except: |
| audio_duration = 30 |
| |
| ai_suggestions = get_ai_processing_suggestions(len(video_files), audio_duration) |
| |
| |
| status_updates = "🤖 OpenAI GPT 正在分析视频内容...\n" |
| video_analysis = analyze_video_content(video_files[0].name if video_files else "", len(video_files)) |
| |
| try: |
| |
| temp_dir = tempfile.mkdtemp() |
| output_dir = os.path.join(temp_dir, f"openai_output_{datetime.now().strftime('%m%d_%H%M')}") |
| os.makedirs(output_dir, exist_ok=True) |
| |
| status_updates += "🎬 开始处理视频文件...\n" |
| |
| |
| video_clips = [] |
| total_source_duration = 0 |
| |
| |
| for i, video_file in enumerate(video_files): |
| status_updates += f"📹 处理第 {i+1}/{len(video_files)} 个视频...\n" |
| |
| clip = VideoFileClip(video_file.name) |
| total_source_duration += clip.duration |
| |
| |
| for start_time_clip in range(0, int(clip.duration), clip_duration): |
| end_time = min(start_time_clip + clip_duration, clip.duration) |
| if end_time - start_time_clip >= 0.5: |
| sub_clip = clip.subclip(start_time_clip, end_time).without_audio() |
| video_clips.append(sub_clip) |
| |
| |
| audio = AudioFileClip(audio_file.name) |
| target_duration = audio.duration |
| |
| |
| random.shuffle(video_clips) |
| |
| status_updates += f"🎵 音频时长: {target_duration:.1f}秒\n" |
| status_updates += f"📊 生成 {len(video_clips)} 个视频片段\n" |
| status_updates += f"🔄 准备输出 {num_output_videos} 个混剪视频...\n" |
| |
| |
| output_files = [] |
| clips_per_video = max(1, len(video_clips) // num_output_videos) |
| |
| for i in range(num_output_videos): |
| start_idx = i * clips_per_video |
| end_idx = start_idx + clips_per_video |
| |
| |
| if i == num_output_videos - 1: |
| end_idx = len(video_clips) |
| |
| selected_clips = video_clips[start_idx:end_idx] |
| |
| if selected_clips: |
| |
| final_video = concatenate_videoclips(selected_clips) |
| |
| |
| if final_video.duration > target_duration: |
| final_video = final_video.subclip(0, target_duration) |
| elif final_video.duration < target_duration: |
| |
| loops_needed = int(target_duration / final_video.duration) + 1 |
| looped_video = concatenate_videoclips([final_video] * loops_needed) |
| final_video = looped_video.subclip(0, target_duration) |
| |
| |
| final_video = final_video.set_audio(audio) |
| |
| |
| final_video = final_video.fx(vfx.mirror_x) |
| |
| |
| output_filename = f"openai_mixcut_{i+1:02d}.mp4" |
| output_path = os.path.join(output_dir, output_filename) |
| |
| final_video.write_videofile( |
| output_path, |
| codec='libx264', |
| audio_codec='aac', |
| temp_audiofile='temp-audio.m4a', |
| remove_temp=True, |
| verbose=False, |
| logger=None |
| ) |
| |
| output_files.append(output_path) |
| |
| |
| final_video.close() |
| |
| |
| for clip in video_clips: |
| clip.close() |
| audio.close() |
| |
| |
| end_time = datetime.now() |
| processing_time = (end_time - start_time).total_seconds() |
| |
| |
| status_updates += "🎯 生成创意标题...\n" |
| ai_titles = generate_creative_titles(num_output_videos) |
| |
| status_updates += "📋 生成项目总结...\n" |
| project_summary = generate_project_summary(num_output_videos, f"{processing_time:.1f}秒") |
| |
| |
| final_status = f"""✅ 处理完成!OpenAI GPT 增强版 |
| |
| 📊 处理统计: |
| • 输入视频: {len(video_files)} 个 |
| • 生成片段: {len(video_clips)} 个 |
| • 输出视频: {len(output_files)} 个 |
| • 处理时长: {processing_time:.1f} 秒 |
| • 音频匹配: {target_duration:.1f} 秒 |
| |
| 🤖 AI 增强功能已完成: |
| • ✓ 内容智能分析 |
| • ✓ 创意标题生成 |
| • ✓ 专业项目总结 |
| • ✓ 处理建议优化 |
| |
| ⏰ 完成时间: {end_time.strftime('%H:%M:%S')}""" |
| |
| return final_status, output_files, video_analysis, ai_titles, project_summary |
| |
| except Exception as e: |
| error_msg = f"""❌ 处理出现错误: {str(e)} |
| |
| 🔧 可能的解决方案: |
| 1. 检查视频文件格式是否支持 |
| 2. 确认音频文件完整性 |
| 3. 减少输出视频数量 |
| 4. 检查系统资源使用情况""" |
| |
| return error_msg, [], ai_suggestions, "", "" |
|
|
| |
| with gr.Blocks( |
| title="pyTovideo2 + OpenAI GPT", |
| theme=gr.themes.Soft(), |
| css=""" |
| .gradio-container { |
| font-family: 'Arial', sans-serif; |
| } |
| .main-header { |
| text-align: center; |
| margin-bottom: 25px; |
| padding: 20px; |
| background: linear-gradient(90deg, #667eea 0%, #764ba2 100%); |
| border-radius: 10px; |
| color: white; |
| } |
| """ |
| ) as demo: |
| |
| |
| gr.HTML(""" |
| <div class="main-header"> |
| <h1 style="margin-bottom: 10px;">🎬 pyTovideo2 + OpenAI GPT</h1> |
| <p style="margin: 0; opacity: 0.9;">AI 驱动的智能视频混剪工具 | GPT-4 内容分析与创意生成</p> |
| </div> |
| """) |
| |
| |
| with gr.Row(): |
| |
| with gr.Column(scale=1): |
| gr.Markdown("### 📤 素材上传") |
| |
| video_input = gr.File( |
| label="🎥 选择视频文件 (支持批量上传)", |
| file_count="multiple", |
| file_types=[".mp4", ".mov", ".avi", ".mkv"], |
| height=130 |
| ) |
| |
| audio_input = gr.File( |
| label="🎵 选择背景音频", |
| file_types=[".mp3", ".wav", ".m4a", ".aac"], |
| height=90 |
| ) |
| |
| gr.Markdown("### ⚙️ 处理参数") |
| |
| with gr.Row(): |
| clip_duration = gr.Number( |
| label="⏱️ 切片时长(秒)", |
| value=2, |
| minimum=1, |
| maximum=8, |
| step=0.5, |
| info="每个视频片段的长度" |
| ) |
| |
| num_videos = gr.Number( |
| label="📊 输出数量", |
| value=3, |
| minimum=1, |
| maximum=6, |
| step=1, |
| info="生成混剪视频的数量" |
| ) |
| |
| |
| process_btn = gr.Button( |
| "🚀 开始 AI 智能处理", |
| variant="primary", |
| size="lg", |
| scale=1 |
| ) |
| |
| |
| gr.Markdown(""" |
| <div style="background: #f0f8ff; padding: 10px; border-radius: 8px; margin-top: 15px;"> |
| <b>🤖 AI 模型信息:</b><br> |
| • 内容分析: GPT-4o-mini<br> |
| • 标题生成: GPT-4o-mini<br> |
| • 项目总结: GPT-4o<br> |
| • 成本优化: 智能模型选择 |
| </div> |
| """) |
| |
| |
| with gr.Column(scale=1): |
| gr.Markdown("### 📊 处理状态") |
| |
| status_output = gr.Textbox( |
| label="🔥 实时处理状态", |
| lines=8, |
| max_lines=12, |
| interactive=False, |
| show_copy_button=True, |
| placeholder="等待开始处理..." |
| ) |
| |
| gr.Markdown("### 📁 输出文件") |
| |
| video_output = gr.File( |
| label="⬇️ 下载混剪视频", |
| file_count="multiple", |
| height=120, |
| interactive=False |
| ) |
| |
| |
| gr.Markdown("---") |
| gr.HTML("<h2 style='text-align: center; color: #4a90e2;'>🧠 OpenAI GPT 智能分析结果</h2>") |
| |
| with gr.Row(): |
| with gr.Column(): |
| gr.Markdown("### 📈 内容分析报告") |
| analysis_output = gr.Textbox( |
| label="🎯 GPT-4 视频内容分析", |
| lines=6, |
| interactive=False, |
| show_copy_button=True, |
| placeholder="AI 分析结果将在这里显示..." |
| ) |
| |
| with gr.Column(): |
| gr.Markdown("### 🏷️ 创意标题推荐") |
| titles_output = gr.Textbox( |
| label="💡 GPT 生成创意标题", |
| lines=6, |
| interactive=False, |
| show_copy_button=True, |
| placeholder="创意标题将在这里显示..." |
| ) |
| |
| |
| gr.Markdown("### 📋 AI 项目分析总结") |
| summary_output = gr.Textbox( |
| label="📊 GPT-4 专业项目总结", |
| lines=5, |
| interactive=False, |
| show_copy_button=True, |
| placeholder="详细的项目分析总结将在这里显示..." |
| ) |
| |
| |
| process_btn.click( |
| fn=process_videos_with_openai, |
| inputs=[video_input, audio_input, clip_duration, num_videos], |
| outputs=[status_output, video_output, analysis_output, titles_output, summary_output], |
| show_progress=True |
| ) |
| |
| |
| gr.Markdown(""" |
| --- |
| ### 📖 使用指南 |
| |
| **🎯 支持格式:** |
| - 视频: MP4, MOV, AVI, MKV |
| - 音频: MP3, WAV, M4A, AAC |
| |
| **💾 建议规格:** |
| - 单个视频 < 200MB |
| - 音频文件 < 50MB |
| - 总处理时间 < 5分钟 |
| |
| **🤖 AI 功能特色:** |
| - ✨ GPT-4 智能内容分析 |
| - 🎨 创意标题自动生成 |
| - 📊 专业项目评估报告 |
| - 💡 个性化优化建议 |
| |
| **⚡ 处理流程:** |
| 1. 上传视频和音频文件 |
| 2. 调整处理参数 |
| 3. 点击开始处理 |
| 4. 等待 AI 分析完成 |
| 5. 下载结果文件 |
| """) |
|
|
| |
| if __name__ == "__main__": |
| demo.launch( |
| share=False, |
| show_error=True, |
| show_tips=True |
| ) |
|
|