aigorithm commited on
Commit
79b85f2
Β·
verified Β·
1 Parent(s): c19f44b
Files changed (2) hide show
  1. app.py +76 -85
  2. requirements.txt +1 -2
app.py CHANGED
@@ -1,17 +1,15 @@
1
  import gradio as gr
2
  from transformers import pipeline
3
  import requests
4
- import random
5
  import html
6
  import base64
7
- import os
8
  import json
9
  from datetime import datetime
10
- from moviepy.editor import VideoFileClip, AudioFileClip, CompositeVideoClip, TextClip
11
 
12
  chat_gen = pipeline("text-generation", model="mistralai/Mistral-7B-Instruct-v0.2")
13
 
14
- # Static voice options
15
  voice_options = {
16
  "Rachel": "EXAVITQu4vr4xnSDxMaL",
17
  "Adam": "21m00Tcm4TlvDq8ikWAM",
@@ -21,100 +19,93 @@ voice_options = {
21
 
22
  library_file = "/tmp/library.json"
23
 
24
- def generate_with_voices(prompt, video, character_inputs):
25
- try:
26
- characters = [c.split(":")[0].strip() for c in character_inputs if ":" in c]
27
- voices = {c.split(":")[0].strip(): c.split(":")[1].strip() for c in character_inputs if ":" in c}
28
-
29
- system_prompt = (
30
- f"Group chat between {', '.join(characters)}. Prompt: {prompt}. "
31
- "Use casual format like: Name: message"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  )
33
- response = chat_gen(system_prompt, max_new_tokens=400)[0]["generated_text"]
34
- chat_lines = [(line.split(':', 1)[0].strip(), line.split(':', 1)[1].strip()) for line in response.splitlines() if ':' in line]
35
-
36
- audio_paths = []
37
- chat_overlay_text = []
38
-
39
- for i, (name, msg) in enumerate(chat_lines):
40
- voice_id = voices.get(name, list(voice_options.values())[0])
41
- eleven_response = requests.post(
42
- f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
43
- headers={
44
- "xi-api-key": os.environ.get("ELEVEN_API_KEY", "demo-key"),
45
- "Content-Type": "application/json"
46
- },
47
- json={ "text": msg, "model_id": "eleven_monolingual_v1" }
48
- )
49
- if eleven_response.status_code == 200:
50
- file_path = f"/tmp/audio_{i}.mp3"
51
- with open(file_path, 'wb') as f:
52
- f.write(eleven_response.content)
53
- audio_paths.append(file_path)
54
-
55
- chat_overlay_text.append(f"{name}: {msg}")
56
-
57
- final_audio = AudioFileClip(audio_paths[0])
58
- for a in audio_paths[1:]:
59
- final_audio = final_audio.append(AudioFileClip(a))
60
-
61
- video_clip = VideoFileClip(video.name).resize(height=480)
62
- video_clip = video_clip.set_audio(final_audio)
63
-
64
- txt = "\n".join(chat_overlay_text)
65
- txt_clip = TextClip(txt, fontsize=24, color='black', bg_color='white', font="Courier").set_duration(video_clip.duration)
66
- txt_clip = txt_clip.set_position((20, 20))
67
-
68
- final = CompositeVideoClip([video_clip, txt_clip])
69
- timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
70
- out_path = f"/tmp/fakechat_{timestamp}.mp4"
71
- final.write_videofile(out_path, codec="libx264", audio_codec="aac")
72
-
73
- # Save to library
74
- if os.path.exists(library_file):
75
- with open(library_file, 'r') as f:
76
- library = json.load(f)
77
- else:
78
- library = []
79
-
80
- library.insert(0, {
81
- "timestamp": timestamp,
82
- "characters": characters,
83
- "prompt": prompt,
84
- "path": out_path
85
- })
86
-
87
- with open(library_file, 'w') as f:
88
- json.dump(library, f, indent=2)
89
-
90
- return out_path
91
- except Exception as e:
92
- return f"Error: {str(e)}"
93
 
94
  def get_library():
95
  if not os.path.exists(library_file):
96
- return "No stories yet."
97
- with open(library_file, 'r') as f:
98
- library = json.load(f)
99
- html_items = [f"<li><a href='file={item['path']}' target='_blank'>{item['timestamp']} β€” {', '.join(item['characters'])}</a></li>" for item in library]
100
- return f"<ul>{''.join(html_items)}</ul>"
101
 
102
- def build_voice_inputs():
103
  return [gr.Textbox(label=f"Character {i+1} (Format: Name:Voice)", placeholder="e.g. Anna:Rachel") for i in range(4)]
104
 
105
  with gr.Blocks() as app:
106
  with gr.Row():
107
  with gr.Column(scale=3):
108
- character_inputs = build_voice_inputs()
109
  prompt = gr.Textbox(label="Scene Prompt")
110
- video = gr.File(label="Upload Background Video (.mp4)", file_types=[".mp4"])
111
- generate_btn = gr.Button("Generate Story")
112
- output = gr.File(label="Download MP4 Story")
113
  with gr.Column(scale=1):
114
- library_html = gr.HTML(label="My Saved Stories")
115
  refresh_btn = gr.Button("πŸ” Refresh Library")
116
 
117
- generate_btn.click(fn=generate_with_voices, inputs=[prompt, video, character_inputs], outputs=output)
118
- refresh_btn.click(fn=get_library, inputs=[], outputs=library_html)
119
 
120
  app.launch()
 
1
  import gradio as gr
2
  from transformers import pipeline
3
  import requests
4
+ import os
5
  import html
6
  import base64
7
+ import random
8
  import json
9
  from datetime import datetime
 
10
 
11
  chat_gen = pipeline("text-generation", model="mistralai/Mistral-7B-Instruct-v0.2")
12
 
 
13
  voice_options = {
14
  "Rachel": "EXAVITQu4vr4xnSDxMaL",
15
  "Adam": "21m00Tcm4TlvDq8ikWAM",
 
19
 
20
  library_file = "/tmp/library.json"
21
 
22
+ def generate_chat_bundle(prompt, character_inputs):
23
+ characters = [c.split(":")[0].strip() for c in character_inputs if ":" in c]
24
+ voices = {c.split(":")[0].strip(): c.split(":")[1].strip() for c in character_inputs if ":" in c}
25
+
26
+ system_prompt = (
27
+ f"Group chat between {', '.join(characters)}. Prompt: {prompt}. "
28
+ "Use casual texting style: Name: message"
29
+ )
30
+ response = chat_gen(system_prompt, max_new_tokens=400)[0]["generated_text"]
31
+ chat_lines = [(line.split(':', 1)[0].strip(), line.split(':', 1)[1].strip()) for line in response.splitlines() if ':' in line]
32
+
33
+ html_chat = ""
34
+ file_paths = []
35
+
36
+ for i, (name, msg) in enumerate(chat_lines):
37
+ color = random.choice(["#DCF8C6", "#FEE2E2", "#EDEDED", "#C7E2FF"])
38
+ html_chat += f"""<div style='margin: 10px; text-align: {'left' if i % 2 == 0 else 'right'}'>
39
+ <div style='display:inline-block; padding: 10px 15px; background: {color}; border-radius: 15px; max-width: 70%;'>
40
+ <strong>{html.escape(name)}:</strong> {html.escape(msg)}
41
+ </div></div>"""
42
+
43
+ voice_id = voices.get(name, list(voice_options.values())[0])
44
+ eleven_response = requests.post(
45
+ f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
46
+ headers={
47
+ "xi-api-key": os.environ.get("ELEVEN_API_KEY", "demo-key"),
48
+ "Content-Type": "application/json"
49
+ },
50
+ json={"text": msg, "model_id": "eleven_monolingual_v1"}
51
  )
52
+
53
+ if eleven_response.status_code == 200:
54
+ file_path = f"/tmp/audio_{i}_{name}.mp3"
55
+ with open(file_path, 'wb') as f:
56
+ f.write(eleven_response.content)
57
+ file_paths.append(file_path)
58
+
59
+ # Save HTML for download
60
+ timestamp = datetime.now().strftime('%Y%m%d-%H%M%S')
61
+ html_path = f"/tmp/fakechat_{timestamp}.html"
62
+ with open(html_path, "w") as f:
63
+ f.write(f"<html><body>{html_chat}</body></html>")
64
+ file_paths.append(html_path)
65
+
66
+ # Save metadata
67
+ if os.path.exists(library_file):
68
+ with open(library_file, "r") as f:
69
+ lib = json.load(f)
70
+ else:
71
+ lib = []
72
+
73
+ lib.insert(0, {
74
+ "timestamp": timestamp,
75
+ "characters": characters,
76
+ "prompt": prompt,
77
+ "html": html_path,
78
+ "audio_files": file_paths[:-1]
79
+ })
80
+
81
+ with open(library_file, "w") as f:
82
+ json.dump(lib, f, indent=2)
83
+
84
+ return file_paths
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
85
 
86
  def get_library():
87
  if not os.path.exists(library_file):
88
+ return "No stories saved yet."
89
+ with open(library_file, "r") as f:
90
+ lib = json.load(f)
91
+ html_links = [f"<li><b>{item['timestamp']}</b>: {', '.join(item['characters'])} β€” <a href='file={item['html']}' target='_blank'>Chat</a></li>" for item in lib]
92
+ return "<ul>" + "".join(html_links) + "</ul>"
93
 
94
+ def build_character_inputs():
95
  return [gr.Textbox(label=f"Character {i+1} (Format: Name:Voice)", placeholder="e.g. Anna:Rachel") for i in range(4)]
96
 
97
  with gr.Blocks() as app:
98
  with gr.Row():
99
  with gr.Column(scale=3):
100
+ characters = build_character_inputs()
101
  prompt = gr.Textbox(label="Scene Prompt")
102
+ generate_btn = gr.Button("🎀 Generate Chat + Audio")
103
+ file_output = gr.File(file_types=[".html", ".mp3"], label="Download Files")
 
104
  with gr.Column(scale=1):
105
+ lib_html = gr.HTML(label="πŸ“ My Saved Stories")
106
  refresh_btn = gr.Button("πŸ” Refresh Library")
107
 
108
+ generate_btn.click(fn=generate_chat_bundle, inputs=[prompt, characters], outputs=file_output)
109
+ refresh_btn.click(fn=get_library, outputs=lib_html)
110
 
111
  app.launch()
requirements.txt CHANGED
@@ -1,5 +1,4 @@
1
  transformers
2
  gradio
3
  torch
4
- requests
5
- moviepy
 
1
  transformers
2
  gradio
3
  torch
4
+ requests