Spaces:
Running
on
Zero
Running
on
Zero
Update app.py
Browse files
app.py
CHANGED
@@ -5,7 +5,26 @@ import os
|
|
5 |
import shutil
|
6 |
import tempfile
|
7 |
from pydub import AudioSegment
|
|
|
8 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
9 |
def process_audio(input_file):
|
10 |
# Load the audio file
|
11 |
audio = AudioSegment.from_file(input_file)
|
@@ -152,13 +171,44 @@ def overlay_audio(original_mp3: str, translated_wav: str, volume_reduction_db: i
|
|
152 |
print(f"Final audio saved at: {temp_file.name}")
|
153 |
return temp_file.name # Return the temporary file path
|
154 |
|
155 |
-
def process_final_combination(audio_in, chosen_translated):
|
156 |
audio_in = process_audio(audio_in)
|
157 |
temp_output_path = overlay_audio(audio_in, chosen_translated)
|
158 |
-
return gr.update(value=temp_output_path, visible=True)
|
159 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
160 |
def hide_previous():
|
161 |
-
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
|
162 |
|
163 |
css="""
|
164 |
div#col-container{
|
@@ -171,6 +221,7 @@ with gr.Blocks(css=css) as demo:
|
|
171 |
with gr.Column(elem_id="col-container"):
|
172 |
gr.Markdown("# Hibiki ")
|
173 |
gr.Markdown("This is a simple demo for Kyutai's Hibiki translation models • Currently supports French to English only.")
|
|
|
174 |
audio_input = gr.Audio(label="Audio IN", type="filepath")
|
175 |
submit_btn = gr.Button("Submit")
|
176 |
output_result = gr.Audio(label="Translated result")
|
@@ -184,6 +235,8 @@ with gr.Blocks(css=css) as demo:
|
|
184 |
)
|
185 |
choose_this_btn = gr.Button("Use this one", scale=1, visible=False)
|
186 |
combined_output = gr.Audio("Combined Outpu", visible=False)
|
|
|
|
|
187 |
with gr.Accordion("Downloadable audio Output list", open=False, visible=False) as result_accordion:
|
188 |
wav_list = gr.Files(label="Output Audio List", visible=False)
|
189 |
|
@@ -196,6 +249,12 @@ with gr.Blocks(css=css) as demo:
|
|
196 |
inputs = [audio_input]
|
197 |
)
|
198 |
|
|
|
|
|
|
|
|
|
|
|
|
|
199 |
dropdown_wav_selector.select(
|
200 |
fn = load_chosen_audio,
|
201 |
inputs = [dropdown_wav_selector],
|
@@ -205,14 +264,20 @@ with gr.Blocks(css=css) as demo:
|
|
205 |
|
206 |
choose_this_btn.click(
|
207 |
fn = process_final_combination,
|
208 |
-
inputs = [audio_input, dropdown_wav_selector],
|
209 |
-
outputs = [combined_output]
|
|
|
|
|
|
|
|
|
|
|
|
|
210 |
)
|
211 |
|
212 |
submit_btn.click(
|
213 |
fn = hide_previous,
|
214 |
inputs = None,
|
215 |
-
outputs = [dropdown_wav_selector, result_accordion, wav_list, choose_this_btn, combined_output]
|
216 |
).then(
|
217 |
fn = infer,
|
218 |
inputs = [audio_input],
|
|
|
5 |
import shutil
|
6 |
import tempfile
|
7 |
from pydub import AudioSegment
|
8 |
+
from moviepy.editor import VideoFileClip, AudioFileClip, concatenate_videoclips, freeze
|
9 |
|
10 |
+
def extract_audio_as_mp3(video_path: str) -> str:
|
11 |
+
"""
|
12 |
+
Extracts the audio from a video file and saves it as a temporary MP3 file.
|
13 |
+
|
14 |
+
:param video_path: Path to the input video file.
|
15 |
+
:return: Path to the temporary MP3 file.
|
16 |
+
"""
|
17 |
+
# Load the video
|
18 |
+
video = VideoFileClip(video_path)
|
19 |
+
|
20 |
+
# Create a temporary file for the extracted audio
|
21 |
+
temp_audio = tempfile.NamedTemporaryFile(delete=False, suffix=".mp3")
|
22 |
+
|
23 |
+
# Extract and export the audio as MP3
|
24 |
+
video.audio.write_audiofile(temp_audio.name, codec="mp3")
|
25 |
+
|
26 |
+
return temp_audio.name # Return the temp file path
|
27 |
+
|
28 |
def process_audio(input_file):
|
29 |
# Load the audio file
|
30 |
audio = AudioSegment.from_file(input_file)
|
|
|
171 |
print(f"Final audio saved at: {temp_file.name}")
|
172 |
return temp_file.name # Return the temporary file path
|
173 |
|
174 |
+
def process_final_combination(audio_in, chosen_translated, video_input):
|
175 |
audio_in = process_audio(audio_in)
|
176 |
temp_output_path = overlay_audio(audio_in, chosen_translated)
|
|
|
177 |
|
178 |
+
if video_input:
|
179 |
+
return gr.update(value=temp_output_path, visible=True), gr.update(visible=True)
|
180 |
+
else:
|
181 |
+
return gr.update(value=temp_output_path, visible=True), gr.update(visible=False)
|
182 |
+
|
183 |
+
def replace_video_audio(video_path: str, new_audio_path: str) -> str:
|
184 |
+
"""Replaces the original audio in the video with the new combined audio,
|
185 |
+
extending video if needed, and saves it to a temp file."""
|
186 |
+
|
187 |
+
# Load video
|
188 |
+
video = VideoFileClip(video_path)
|
189 |
+
|
190 |
+
# Load new audio
|
191 |
+
new_audio = AudioFileClip(new_audio_path)
|
192 |
+
|
193 |
+
# If the new audio is longer, extend the video by freezing the last frame
|
194 |
+
if new_audio.duration > video.duration:
|
195 |
+
last_frame = video.get_frame(video.duration - 0.1) # Get last frame
|
196 |
+
freeze_frame = freeze(video, t=video.duration - 0.1, freeze_duration=new_audio.duration - video.duration)
|
197 |
+
video = concatenate_videoclips([video, freeze_frame])
|
198 |
+
|
199 |
+
# Set new audio
|
200 |
+
video = video.set_audio(new_audio)
|
201 |
+
|
202 |
+
# Create a temporary file for the video
|
203 |
+
temp_video = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4")
|
204 |
+
|
205 |
+
# Export video with appropriate codec
|
206 |
+
video.write_videofile(temp_video.name, codec="libx264", audio_codec="aac")
|
207 |
+
|
208 |
+
return gr.update(value=temp_video.name, visible=True) # Return path to temp video file
|
209 |
+
|
210 |
def hide_previous():
|
211 |
+
return gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False), gr.update(visible=False)
|
212 |
|
213 |
css="""
|
214 |
div#col-container{
|
|
|
221 |
with gr.Column(elem_id="col-container"):
|
222 |
gr.Markdown("# Hibiki ")
|
223 |
gr.Markdown("This is a simple demo for Kyutai's Hibiki translation models • Currently supports French to English only.")
|
224 |
+
video_input = gr.Video(label="Video IN")
|
225 |
audio_input = gr.Audio(label="Audio IN", type="filepath")
|
226 |
submit_btn = gr.Button("Submit")
|
227 |
output_result = gr.Audio(label="Translated result")
|
|
|
235 |
)
|
236 |
choose_this_btn = gr.Button("Use this one", scale=1, visible=False)
|
237 |
combined_output = gr.Audio("Combined Outpu", visible=False)
|
238 |
+
apply_to_video_btn = gr.Button("Apply to video", visible=False)
|
239 |
+
final_video_out = gr.Video(label="Video + Translated Audio", visible=False)
|
240 |
with gr.Accordion("Downloadable audio Output list", open=False, visible=False) as result_accordion:
|
241 |
wav_list = gr.Files(label="Output Audio List", visible=False)
|
242 |
|
|
|
249 |
inputs = [audio_input]
|
250 |
)
|
251 |
|
252 |
+
video_input.upload(
|
253 |
+
fn = extract_audio_as_mp3,
|
254 |
+
inputs = [video_input],
|
255 |
+
outputs = [audio_input]
|
256 |
+
)
|
257 |
+
|
258 |
dropdown_wav_selector.select(
|
259 |
fn = load_chosen_audio,
|
260 |
inputs = [dropdown_wav_selector],
|
|
|
264 |
|
265 |
choose_this_btn.click(
|
266 |
fn = process_final_combination,
|
267 |
+
inputs = [audio_input, dropdown_wav_selector, video_input],
|
268 |
+
outputs = [combined_output, apply_to_video_btn]
|
269 |
+
)
|
270 |
+
|
271 |
+
apply_to_video_btn.click(
|
272 |
+
fn = replace_video_audio,
|
273 |
+
inputs = [combined_output, video_input],
|
274 |
+
outputs = [final_video_out]
|
275 |
)
|
276 |
|
277 |
submit_btn.click(
|
278 |
fn = hide_previous,
|
279 |
inputs = None,
|
280 |
+
outputs = [dropdown_wav_selector, result_accordion, wav_list, choose_this_btn, combined_output, apply_to_video_btn, final_video_out]
|
281 |
).then(
|
282 |
fn = infer,
|
283 |
inputs = [audio_input],
|