vilarin commited on
Commit
d8ad8f9
Β·
verified Β·
1 Parent(s): 236ae5b

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +198 -0
app.py ADDED
@@ -0,0 +1,198 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #Codes from killerz3/PodGen & eswardivi/Podcastify
2
+ import subprocess
3
+ subprocess.run(
4
+ 'pip install flash-attn --no-build-isolation',
5
+ env={'FLASH_ATTENTION_SKIP_CUDA_BUILD': "TRUE"},
6
+ shell=True
7
+ )
8
+
9
+ import json
10
+ import spaces
11
+ import httpx
12
+ import asyncio
13
+ import edge_tts
14
+ import torch
15
+ import gradio as gr
16
+ import gradio_client
17
+ from pydub import AudioSegment
18
+ from transformers import AutoModelForCausalLM, AutoTokenizer
19
+
20
+ from moviepy.editor import AudioFileClip, concatenate_audioclips
21
+
22
+ system_prompt = '''
23
+ You are an educational podcast generator. You have to create a podcast between Alice and Bob that gives an overview of the News given by the user.
24
+ Please provide the script in the following JSON format directly and only include it:
25
+ {
26
+ "title": "[string]",
27
+ "content": {
28
+ "Alice_0": "[string]",
29
+ "BOB_0": "[string]",
30
+ ...
31
+ }
32
+ }
33
+ Please note that the text you generate now must be based on the tone of people's daily life.
34
+ And the punctuation marks only include commas and periods.
35
+ '''
36
+
37
+ DESCRIPTION = '''
38
+ <div>
39
+ <h1 style="text-align: center;">Musen</h1>
40
+ <p>A podcast talking about the link's content you provided.</p>
41
+ <p>πŸ”Ž Paste a website link with http/https.</p>
42
+ <p>πŸ¦• Generate podcast. </p>
43
+ </div>
44
+ '''
45
+
46
+ css = """
47
+ h1 {
48
+ text-align: center;
49
+ display: block;
50
+ }
51
+ footer {
52
+ display:none !important
53
+ }
54
+ """
55
+
56
+ model = AutoModelForCausalLM.from_pretrained(
57
+ "Qwen/Qwen1.5-MoE-A2.7B-Chat-GPTQ-Int4",
58
+ torch_dtype="auto",
59
+ device_map="auto"
60
+ )
61
+
62
+ tokenizer = AutoTokenizer.from_pretrained("Qwen/Qwen1.5-MoE-A2.7B-Chat-GPTQ-Int4")
63
+
64
+
65
+ async def validate_url(url):
66
+ try:
67
+ response = httpx.get(url, timeout=60.0)
68
+ response.raise_for_status()
69
+ return response.text
70
+ except httpx.RequestError as e:
71
+ return f"An error occurred while requesting {url}: {str(e)}"
72
+ except httpx.HTTPStatusError as e:
73
+ return f"Error response {e.response.status_code} while requesting {url}"
74
+ except Exception as e:
75
+ return f"An unexpected error occurred: {str(e)}"
76
+
77
+ async def fetch_text(url):
78
+ print("Entered Webpage Extraction")
79
+ prefix_url = "https://r.jina.ai/"
80
+ full_url = prefix_url + url
81
+ print(full_url)
82
+ print("Exited Webpage Extraction")
83
+ return validate_url(full_url)
84
+
85
+ async def text_to_speech(text, voice, filename):
86
+ communicate = edge_tts.Communicate(text, voice)
87
+ await communicate.save(filename)
88
+
89
+
90
+ async def gen_show(script):
91
+ title = script['title']
92
+ content = script['content']
93
+
94
+ temp_files = []
95
+
96
+ tasks = []
97
+ for key, text in content.items():
98
+ speaker = key.split('_')[0] # Extract the speaker name
99
+ index = key.split('_')[1] # Extract the dialogue index
100
+ voice = "en-US-JennyNeural" if speaker == "Alice" else "en-US-GuyNeural"
101
+
102
+ # Create temporary file for each speaker's dialogue
103
+ temp_file = tempfile.NamedTemporaryFile(suffix='.mp3', delete=False)
104
+ temp_files.append(temp_file.name)
105
+
106
+ filename = temp_file.name
107
+ tasks.append(text_to_speech(text, voice, filename))
108
+ print(f"Generated audio for {speaker}_{index}: {filename}")
109
+
110
+ await asyncio.gather(*tasks)
111
+
112
+ # Combine the audio files using moviepy
113
+ audio_clips = [AudioFileClip(temp_file) for temp_file in temp_files]
114
+ combined = concatenate_audioclips(audio_clips)
115
+
116
+ # Create temporary file for the combined output
117
+ output_filename = tempfile.NamedTemporaryFile(suffix='.mp3', delete=False).name
118
+
119
+ # Save the combined file
120
+ combined.write_audiofile(output_filename)
121
+ print(f"Combined audio saved as: {output_filename}")
122
+
123
+ # Clean up temporary files
124
+ for temp_file in temp_files:
125
+ os.remove(temp_file)
126
+ print(f"Deleted temporary file: {temp_file}")
127
+
128
+ return output_filename
129
+
130
+ @spaces.GPU(duration=100)
131
+ async def generator(link):
132
+ if not link.startswith("http://") and not article_url.startswith("https://"):
133
+ return "URL must start with 'http://' or 'https://'",None
134
+
135
+ text = fetch_text(link)
136
+
137
+ if "Error" in text:
138
+ return text, None
139
+
140
+ prompt = f"News: {text}, json:"
141
+
142
+ messages = [
143
+ {"role": "system", "content": system_prompt},
144
+ {"role": "user", "content": prompt},
145
+ ]
146
+
147
+ answer = tokenizer.apply_chat_template(
148
+ messages,
149
+ tokenize=False,
150
+ add_generation_prompt=True
151
+ )
152
+ model_inputs = tokenizer([answer], return_tensors="pt").to(0)
153
+
154
+ generated_ids = model.generate(
155
+ model_inputs.input_ids,
156
+ max_new_tokens=512
157
+ )
158
+
159
+ generated_ids = [
160
+ output_ids[len(input_ids):] for input_ids, output_ids in zip(model_inputs.input_ids, generated_ids)
161
+ ]
162
+
163
+ results = tokenizer.batch_decode(generated_ids, skip_special_tokens=True)[0]
164
+
165
+ generated_script = results
166
+
167
+ print("Generated Script:"+generated_script)
168
+
169
+ # Check if the generated_script is empty or not valid JSON
170
+ if not generated_script or not generated_script.strip().startswith('{'):
171
+ raise ValueError("Failed to generate a valid script.")
172
+
173
+
174
+ script_json = json.loads(generated_script) # Use the generated script as input
175
+ output_filename = await gen_show(script_json)
176
+ print("Output File:"+output_filename)
177
+
178
+ # Read the generated audio file
179
+ return output_filename
180
+
181
+ with gr.Blocks(theme='soft', css=css, title="Musen") as iface:
182
+ with gr.Accordion(""):
183
+ gr.Markdown(DESCRIPTION)
184
+ with gr.Row():
185
+ output_box = gr.Audio(label="Podcast", type="filepath", interactive=False, autoplay=True, elem_classes="audio") # Create an output textbox
186
+ with gr.Row():
187
+ input_box = gr.Textbox(label="Link", placeholder="Enter a http link")
188
+ with gr.Row():
189
+ submit_btn = gr.Button("πŸš€ Send") # Create a submit button
190
+ clear_btn = gr.ClearButton(output_box, value="πŸ—‘οΈ Clear") # Create a clear button
191
+
192
+ # Set up the event listeners
193
+ submit_btn.click(generator, inputs=input_box, outputs=output_box)
194
+
195
+
196
+ #gr.close_all()
197
+
198
+ iface.queue().launch(show_api=False) # Launch the Gradio interface