SPACERUNNER99 commited on
Commit
285494b
·
verified ·
1 Parent(s): bbc83e3

Create dub.py

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