Update app.py
Browse filesadd tempo change
app.py
CHANGED
@@ -9,6 +9,8 @@ import re
|
|
9 |
import subprocess
|
10 |
import numpy as np
|
11 |
import soundfile as sf
|
|
|
|
|
12 |
|
13 |
ASR_API = "http://astarwiz.com:9998/asr"
|
14 |
TTS_SPEAK_SERVICE = 'http://astarwiz.com:9603/speak'
|
@@ -50,7 +52,6 @@ def replace_audio_in_video(video_path, audio_path, output_path):
|
|
50 |
return output_path
|
51 |
|
52 |
def replace_audio_and_generate_video(temp_video_path, gradio_audio):
|
53 |
-
print (type(temp_video_path), type(gradio_audio))
|
54 |
if not temp_video_path or gradio_audio is None:
|
55 |
return "Both video and audio are required to replace audio.", None
|
56 |
|
@@ -64,39 +65,43 @@ def replace_audio_and_generate_video(temp_video_path, gradio_audio):
|
|
64 |
if not isinstance(audio_data, np.ndarray):
|
65 |
audio_data = np.array(audio_data)
|
66 |
|
67 |
-
# Create a temporary WAV file
|
68 |
with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_audio_file:
|
69 |
-
|
70 |
-
sf.write(
|
71 |
|
72 |
-
#
|
73 |
-
|
|
|
|
|
74 |
|
75 |
-
|
76 |
-
|
77 |
-
|
78 |
-
|
79 |
-
|
80 |
-
|
81 |
-
|
82 |
-
|
83 |
-
|
84 |
-
if not temp_video_path or not audio_path:
|
85 |
-
return "Both video and audio are required to replace audio.", None
|
86 |
|
87 |
-
|
88 |
-
|
|
|
|
|
89 |
|
90 |
# Generate output video path
|
91 |
output_video_path = os.path.join(tempfile.gettempdir(), f"output_{uuid.uuid4()}.mp4")
|
92 |
|
93 |
try:
|
94 |
-
replace_audio_in_video(temp_video_path,
|
95 |
return "Audio replaced successfully.", output_video_path
|
96 |
except subprocess.CalledProcessError as e:
|
97 |
return f"Error replacing audio: {str(e)}", None
|
98 |
-
|
99 |
-
|
|
|
|
|
100 |
|
101 |
|
102 |
def fetch_youtube_id(youtube_url: str) -> str:
|
|
|
9 |
import subprocess
|
10 |
import numpy as np
|
11 |
import soundfile as sf
|
12 |
+
import sox
|
13 |
+
from moviepy.editor import VideoFileClip
|
14 |
|
15 |
ASR_API = "http://astarwiz.com:9998/asr"
|
16 |
TTS_SPEAK_SERVICE = 'http://astarwiz.com:9603/speak'
|
|
|
52 |
return output_path
|
53 |
|
54 |
def replace_audio_and_generate_video(temp_video_path, gradio_audio):
|
|
|
55 |
if not temp_video_path or gradio_audio is None:
|
56 |
return "Both video and audio are required to replace audio.", None
|
57 |
|
|
|
65 |
if not isinstance(audio_data, np.ndarray):
|
66 |
audio_data = np.array(audio_data)
|
67 |
|
68 |
+
# Create a temporary WAV file for the original audio
|
69 |
with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_audio_file:
|
70 |
+
original_audio_path = temp_audio_file.name
|
71 |
+
sf.write(original_audio_path, audio_data, sample_rate)
|
72 |
|
73 |
+
# Get video duration
|
74 |
+
video_clip = VideoFileClip(temp_video_path)
|
75 |
+
video_duration = video_clip.duration
|
76 |
+
video_clip.close()
|
77 |
|
78 |
+
# Get audio duration
|
79 |
+
audio_duration = len(audio_data) / sample_rate
|
80 |
+
|
81 |
+
# Calculate tempo factor
|
82 |
+
tempo_factor = audio_duration / video_duration
|
83 |
+
|
84 |
+
# Create a temporary WAV file for the tempo-adjusted audio
|
85 |
+
with tempfile.NamedTemporaryFile(suffix='.wav', delete=False) as temp_audio_file:
|
86 |
+
adjusted_audio_path = temp_audio_file.name
|
|
|
|
|
87 |
|
88 |
+
# Adjust audio tempo
|
89 |
+
tfm = sox.Transformer()
|
90 |
+
tfm.tempo(tempo_factor, 's')
|
91 |
+
tfm.build(original_audio_path, adjusted_audio_path)
|
92 |
|
93 |
# Generate output video path
|
94 |
output_video_path = os.path.join(tempfile.gettempdir(), f"output_{uuid.uuid4()}.mp4")
|
95 |
|
96 |
try:
|
97 |
+
replace_audio_in_video(temp_video_path, adjusted_audio_path, output_video_path)
|
98 |
return "Audio replaced successfully.", output_video_path
|
99 |
except subprocess.CalledProcessError as e:
|
100 |
return f"Error replacing audio: {str(e)}", None
|
101 |
+
finally:
|
102 |
+
os.unlink(original_audio_path) # Clean up the original audio file
|
103 |
+
os.unlink(adjusted_audio_path) # Clean up the adjusted audio file
|
104 |
+
|
105 |
|
106 |
|
107 |
def fetch_youtube_id(youtube_url: str) -> str:
|