SPACERUNNER99 commited on
Commit
7fba440
·
verified ·
1 Parent(s): 0d4cdde

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +154 -0
app.py ADDED
@@ -0,0 +1,154 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ import subprocess
4
+ from pydub import AudioSegment
5
+ from moviepy import VideoFileClip, AudioFileClip, CompositeAudioClip
6
+ from pydub import effects
7
+ import os
8
+ import pysrt
9
+ import json
10
+ import time
11
+ from moviepy import VideoFileClip, AudioFileClip, AudioClip
12
+ import os
13
+ import gradio as gr
14
+ API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzeXN0ZW0iOiJzYWhhYiIsImNyZWF0ZVRpbWUiOiIxNDAzMTIwNTE0MTgzMDM2MyIsInVuaXF1ZUZpZWxkcyI6eyJ1c2VybmFtZSI6IjFlZDZjN2M1LWVjNTktNGI4Yi1iYThkLTk1NTk1ZWQ0MmNhMCJ9LCJkYXRhIjp7InNlcnZpY2VJRCI6ImRmNTNhNzgwLTIxNTgtNDUyNC05MjQ3LWM2ZjBiYWQzZTc3MCIsInJhbmRvbVRleHQiOiJvYlNXciJ9LCJncm91cE5hbWUiOiIwMmYzMWRmM2IyMjczMmJkMDNmYjBlYjU2ZjE1MGEzZCJ9.QakcV3rPn7bji7ur0VPmCzHLWiOs2NXEGw9ILyhpgOw"
15
+
16
+
17
+
18
+ def generate_tts_audio(persian_text, output_file):
19
+ api_url = "https://partai.gw.isahab.ir/TextToSpeech/v1/speech-synthesys"
20
+ proxies = {
21
+ "https" : "https://free.shecan.ir/dns-query"
22
+ }
23
+ headers = {
24
+ 'Content-Type': 'application/json',
25
+ 'gateway-token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzeXN0ZW0iOiJzYWhhYiIsImNyZWF0ZVRpbWUiOiIxNDAzMTIwNTE0MTgzMDM2MyIsInVuaXF1ZUZpZWxkcyI6eyJ1c2VybmFtZSI6IjFlZDZjN2M1LWVjNTktNGI4Yi1iYThkLTk1NTk1ZWQ0MmNhMCJ9LCJkYXRhIjp7InNlcnZpY2VJRCI6ImRmNTNhNzgwLTIxNTgtNDUyNC05MjQ3LWM2ZjBiYWQzZTc3MCIsInJhbmRvbVRleHQiOiJvYlNXciJ9LCJncm91cE5hbWUiOiIwMmYzMWRmM2IyMjczMmJkMDNmYjBlYjU2ZjE1MGEzZCJ9.QakcV3rPn7bji7ur0VPmCzHLWiOs2NXEGw9ILyhpgOw'
26
+ }
27
+ payload = json.dumps({
28
+ "data": persian_text,
29
+ "filePath": "true",
30
+ "base64": "0",
31
+ "checksum": "1",
32
+ "speaker": "2"
33
+ })
34
+ response = requests.request("POST", api_url, headers=headers, data=payload, proxies=proxies)
35
+ link = response.text.split('"')[11]
36
+ link = "https://"+link
37
+ print(link)
38
+ responseD = requests.get(link, stream=True)
39
+ responseD.raise_for_status()
40
+ if responseD:
41
+ with open(output_file, 'wb') as file:
42
+ for chunk in responseD.iter_content(chunk_size=8192):
43
+ if chunk:
44
+ file.write(chunk)
45
+ file.close()
46
+ print(f"Downloaded successfully")
47
+ time.sleep(10)
48
+ return "video.mp4"
49
+ else:
50
+ print(f"Failed to generate TTS audio: {response.status_code} - {response.text}")
51
+ return False
52
+
53
+ def generate_audio_segments(segments, output_dir):
54
+ audio_files = []
55
+ for index, segment in enumerate(segments):
56
+ audio_file = os.path.join(output_dir, f"segment_{index}.mp3")
57
+ max_retries = 3
58
+ retries = 0
59
+ while retries < max_retries:
60
+ try:
61
+ if generate_tts_audio(segment.text, audio_file): # Assuming this returns True/False based on success
62
+ audio_files.append(((f"{segment.start} --> {segment.end}"), audio_file))
63
+ break # If successful, move to the next segment
64
+ # If the above fails (returns False or raises an exception), wait and retry
65
+ retries += 1
66
+ if retries < max_retries:
67
+ time.sleep(30) # Wait for 30 seconds before retrying
68
+ except Exception as e:
69
+ if retries == max_retries - 1: # Last retry attempt
70
+ raise RuntimeError(f"Failed to generate audio after {max_retries} attempts for segment: {segment.text}") from e
71
+ else:
72
+ # If all retries failed (loop completed without breaking)
73
+ raise RuntimeError(f"Failed to generate audio after {max_retries} attempts for segment: {segment.text}")
74
+ return audio_files
75
+
76
+ def srt_time_to_seconds(srt_time):
77
+ hours, minutes, seconds = srt_time.split(':')
78
+ seconds, milliseconds = seconds.split(',')
79
+ total_seconds = int(hours) * 3600 + int(minutes) * 60 + int(seconds) + int(milliseconds) / 1000
80
+ return total_seconds
81
+
82
+ def render_dubbed_video(input_video, audio_files, output_video):
83
+ # Load the input video and remove its audio
84
+ video = VideoFileClip(input_video)
85
+ video_no_audio = video.without_audio()
86
+ print("Video duration (ms):")
87
+ print(video_no_audio.duration * 1000)
88
+ # Get total video duration in milliseconds
89
+ video_duration_in_seconds = video_no_audio.duration
90
+ video_duration_in_ms = video_duration_in_seconds * 1000
91
+ audio_canva = AudioSegment.silent(duration=video_duration_in_ms)
92
+ for timestamp, audio_file in audio_files:
93
+ start_str, end_str = timestamp.split(' --> ')
94
+ start_sec = srt_time_to_seconds(start_str) * 1000
95
+ end_sec = srt_time_to_seconds(end_str) * 1000
96
+ # Load the audio file
97
+ audio = AudioSegment.from_file(audio_file)
98
+ original_duration_ms = len(audio)
99
+ available_slot = end_sec - start_sec
100
+ if available_slot <= 0:
101
+ print(f"Invalid timestamp for {audio_file}. Skipping.")
102
+ continue
103
+ elif original_duration_ms > available_slot:
104
+ speed_factor = min(original_duration_ms / available_slot, 1.2)
105
+ audio = audio.speedup(speed_factor)
106
+ # Append the processed audio to the canvas
107
+ audio_canva = audio_canva.overlay(audio, position=start_sec)
108
+ # Export the combined audio to a temporary file
109
+ combined_audio_file = "combined_audio.mp3"
110
+ audio_canva.export(combined_audio_file, format="mp3")
111
+ # Load the combined audio using MoviePy
112
+ new_audio = AudioFileClip(combined_audio_file)
113
+ # Set the new audio to the video
114
+ final_video = video_no_audio.with_audio(new_audio)
115
+ # Write the output video file
116
+ final_video.write_videofile(output_video, codec="libx264", audio_codec="aac")
117
+ # Clean up temporary files
118
+ video.close()
119
+ new_audio.close()
120
+ final_video.close()
121
+
122
+ def dub(srt, input_video):
123
+ # Step 1: Parse the SRT-like text
124
+ output_video = "video_out.mp4"
125
+ subtitles = pysrt.open(srt, encoding="utf-8")
126
+ print("Parsed segments:", subtitles)
127
+ # Step 2: Translation (commented out as input is already Persian)
128
+ # Step 3: Generate audio for each Persian segment
129
+ output_dir = "audio_segments"
130
+ os.makedirs(output_dir, exist_ok=True)
131
+ audio_files = generate_audio_segments(subtitles, output_dir)
132
+ # Step 4: Render the dubbed video
133
+ render_dubbed_video(input_video, audio_files, output_video)
134
+ # Clean up audio segments directory
135
+ for _, audio_file in audio_files:
136
+ os.remove(audio_file)
137
+ os.rmdir(output_dir)
138
+
139
+ return output_video
140
+
141
+ with gr.Blocks() as demo:
142
+ gr.Markdown("Start typing below and then click **Run** to see the progress and final output.")
143
+ with gr.Column():
144
+ srt_file = gr.File()
145
+ video_in = gr.Video()
146
+ output_video = gr.Video()
147
+ btn = gr.Button("Create")
148
+ btn.click(
149
+ fn=dub,
150
+ inputs=[srt_file, video_in],
151
+ outputs=output_video
152
+ )
153
+
154
+ demo.launch(debug=True)