kavehtaheri commited on
Commit
a0cb076
·
verified ·
1 Parent(s): f285b4b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +65 -155
app.py CHANGED
@@ -7,8 +7,8 @@ import ffmpeg
7
  from faster_whisper import WhisperModel
8
  import requests
9
  import json
10
- import arabic_reshaper # pip install arabic-reshaper
11
- from bidi.algorithm import get_display # pip install python-bidi
12
  from moviepy import VideoFileClip, TextClip, CompositeVideoClip, AudioFileClip, ImageClip
13
  import pysrt
14
  import instaloader
@@ -17,10 +17,10 @@ import concurrent.futures
17
  import re
18
  from io import BytesIO
19
  from PIL import Image
20
- api_key = "268976:66f4f58a2a905"
21
-
22
-
23
 
 
24
 
25
  def fetch_data(url):
26
  try:
@@ -70,9 +70,9 @@ def merge_files(filename, num_parts):
70
  def download_file_in_parallel(link, size, num_threads=4):
71
  url = link.split("#")[0]
72
  filename = link.split("#")[1]
73
- print(url+" filename: "+filename)
74
  response = requests.head(url)
75
- #file_size = int(response.headers['Content-Length'])
76
  chunk_size = size // num_threads
77
 
78
  ranges = [(i * chunk_size, (i + 1) * chunk_size - 1) for i in range(num_threads)]
@@ -89,88 +89,15 @@ def download_file_in_parallel(link, size, num_threads=4):
89
  merge_files(filename, num_threads)
90
  print(f'Downloaded successfully: {filename}')
91
 
92
-
93
-
94
- def one_youtube(link, api_key):
95
-
96
- # Fetch video ID
97
- video_id_url = f"https://one-api.ir/youtube/?token={api_key}&action=getvideoid&link={link}"
98
- video_data = fetch_data(video_id_url)
99
- if not video_data:
100
- return None, None
101
-
102
- video_id = video_data["result"]
103
-
104
- # Fetch video data
105
- filter_option = "" # Replace with your filter option
106
- video_data_url = f"https://youtube.one-api.ir/?token={api_key}&action=fullvideo&id={video_id}&filter={filter_option}"
107
- video_data_2 = fetch_data(video_data_url)
108
- if not video_data_2:
109
- return None, None
110
-
111
- formats_list = video_data_2["result"]["formats"]
112
- file_name = video_data_2["result"]["title"]
113
- video_name = f'{file_name}.mp4'
114
- audio_name = f'{file_name}.mp3'
115
-
116
- for f in formats_list:
117
- if f["format_note"] == "360p":
118
- download_id = f["id"]
119
- video_size = f["filesize"]
120
- for f in formats_list:
121
- if f["format_note"] == "medium":
122
- audio_id = f["id"]
123
- audio_size = f["filesize"]
124
-
125
- if not download_id or not audio_id:
126
- return None, None
127
-
128
- # Fetch video and audio links
129
- video_link_url = f"https://youtube.one-api.ir/?token={api_key}&action=download&id={download_id}"
130
- audio_link_url = f"https://youtube.one-api.ir/?token={api_key}&action=download&id={audio_id}"
131
- video_link_data = fetch_data(video_link_url)
132
- audio_link_data = fetch_data(audio_link_url)
133
- if not video_link_data or not audio_link_data:
134
- return None, None
135
-
136
- video_link = video_link_data["result"]["link"]
137
- audio_link = audio_link_data["result"]["link"]
138
- vid_str=video_link+"#"+video_name
139
- audio_str=audio_link+"#"+audio_name
140
- # Download video and audio files
141
- print(video_size , audio_size)
142
- download_file_in_parallel(vid_str, video_size)
143
- download_file_in_parallel(audio_str, audio_size)
144
-
145
- return video_name, audio_name
146
-
147
-
148
- # Define your functions here
149
- def yt_download(url):
150
- yt = YouTube(url)
151
- print(yt.title)
152
- video_path = f"{yt.title}.mp4"
153
- ys = yt.streams.get_highest_resolution()
154
- print(ys)
155
- ys.download()
156
- return video_path, yt.title
157
-
158
- def download_image(url, save_path='downloaded_image.jpg'):
159
- response = requests.get(url)
160
- image = Image.open(BytesIO(response.content))
161
- image.save(save_path)
162
- return save_path
163
-
164
  def insta_oneapi(url, api_key):
165
  shortcode = url.split("/")[-2]
166
  print(shortcode)
167
- url_one="https://api.one-api.ir/instagram/v1/post/?shortcode="+shortcode
168
- request_body = [{"shortcode": shortcode},]
169
  headers = {"one-api-token": api_key, "Content-Type": "application/json"}
170
  response = requests.get(url_one, headers=headers)
171
  print(response)
172
  if response.status_code == 200:
173
-
174
  result = response.json()
175
  try:
176
  time.sleep(10)
@@ -182,7 +109,7 @@ def insta_oneapi(url, api_key):
182
  file.write(chunk)
183
  file.close()
184
  print(f"Downloaded successfully")
185
- image_url = result["result"]['media'][0]["cover"]
186
  image_file_path = download_image(image_url)
187
  return "video.mp4", image_file_path
188
  except requests.exceptions.RequestException as e:
@@ -191,48 +118,11 @@ def insta_oneapi(url, api_key):
191
  print(f"Error: {response.status_code}, {response.text}")
192
  return None
193
 
194
-
195
- def insta_download(permalink):
196
- # Create an instance of Instaloader
197
- L = instaloader.Instaloader()
198
-
199
- try:
200
- # Extract the shortcode from the permalink
201
- if "instagram.com/reel/" in permalink:
202
- shortcode = permalink.split("instagram.com/reel/")[-1].split("/")[0]
203
- elif "instagram.com/p/" in permalink:
204
- shortcode = permalink.split("instagram.com/p/")[-1].split("/")[0]
205
- else:
206
- raise ValueError("Invalid permalink format")
207
-
208
- # Load the post using the shortcode
209
- post = instaloader.Post.from_shortcode(L.context, shortcode)
210
-
211
- # Check if the post is a video
212
- if not post.is_video:
213
- raise ValueError("The provided permalink is not a video.")
214
-
215
- # Get the video URL
216
- video_url = post.video_url
217
-
218
- # Extract the filename from the URL
219
- filename = video_url.split("/")[-1]
220
- # Remove query parameters
221
- filename = filename.split("?")[0]
222
-
223
- # Download the video using requests
224
- response = requests.get(video_url, stream=True)
225
- response.raise_for_status() # Raise an error for bad responses
226
-
227
- # Save the content to a file
228
- with open(filename, 'wb') as file:
229
- for chunk in response.iter_content(chunk_size=8192):
230
- file.write(chunk)
231
-
232
- print(f"Downloaded video {filename} successfully.")
233
- return filename
234
- except Exception as e:
235
- print(f"Failed to download video from {permalink}: {e}")
236
 
237
  def extract_audio(input_video_name):
238
  # Define the input video file and output audio file
@@ -278,7 +168,7 @@ def generate_subtitle_file(language, segments, input_video_name):
278
  for index, segment in enumerate(segments):
279
  segment_start = format_time(segment.start)
280
  segment_end = format_time(segment.end)
281
- text += f"{str(index+1)} \n"
282
  text += f"{segment_start} --> {segment_end} \n"
283
  text += f"{segment.text} \n"
284
  text += "\n"
@@ -312,7 +202,7 @@ def enhance_text(api_key, text, google):
312
  request_body = [{
313
  "role": "user",
314
  "content": f"{text} ROLE: Expert translator for Persian motivational anime subtitles. TASK: Translate input English SRT (`[X.XXs -> Y.YYs] English text`) to Persian SRT. REQUIREMENTS: 1. STRICT FORMAT: Output MUST be `[X.XXs -> Y.YYs] Persian Text` per line. 2. TIMESTAMPS: CRITICAL - NEVER change timestamps; copy EXACTLY. 3. TRANSLATION: Create motivational, touching, natural, understandable Persian; capture spirit, avoid literalism. 4. LENGTH: Ensure Persian text is concise & readable in time. AVOID: Format errors, timestamp changes, unnatural translation, overly long text. in respose dont add any thing exept for the srt formated translation.Now translate:"
315
- },]
316
 
317
  # Add the API key to the request
318
  headers = {
@@ -360,46 +250,73 @@ def time_to_seconds(time_obj):
360
  def create_subtitle_clips(subtitles, videosize, fontsize, font, color, debug):
361
  subtitle_clips = []
362
  for subtitle in subtitles:
363
- start_time = time_to_seconds(subtitle.start) # Add 2 seconds offset
364
  end_time = time_to_seconds(subtitle.end)
365
  duration = end_time - start_time
366
  video_width, video_height = videosize
367
- max_width = video_width * 0.8
368
  max_height = video_height * 0.2
369
- #reshaped_text = arabic_reshaper.reshape(subtitle.text)
370
- #bidi_text = get_display(reshaped_text)
371
- text_clip = TextClip(font, subtitle.text, font_size=fontsize, size=(int(video_width * 0.8), int(video_height * 0.2)) ,text_align="center" ,color=color, method='caption').with_start(start_time).with_duration(duration)
 
372
  subtitle_x_position = 'center'
373
  subtitle_y_position = video_height * 0.68
374
  text_position = (subtitle_x_position, subtitle_y_position)
375
  subtitle_clips.append(text_clip.with_position(text_position))
376
  return subtitle_clips
377
 
 
 
 
378
 
 
 
 
379
 
380
- def process_video(url, type):
381
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
382
 
383
- if type=="insta":
384
- input_video, image_path=insta_oneapi(url, api_key)
 
385
  input_video_name = input_video.replace(".mp4", "")
386
  video = VideoFileClip(input_video)
387
  image_clip = ImageClip(image_path).with_duration(1)
388
- # Set the position and size of the image (optional)
389
  image_clip = image_clip.with_position(("center", "center")).resized(height=video.size[1])
390
  first_video = CompositeVideoClip([video.with_start(1), image_clip])
391
- input_video = input_video_name+"_cover.mp4"
392
- input_video_name = input_video.replace(".mp4", "")
393
  first_video.write_videofile(input_video, codec="libx264", audio_codec="aac", logger=None)
394
  input_audio = extract_audio(input_video)
395
- elif type=="youtube":
396
- input_video, input_audio = one_youtube(url, api_key)
397
- input_video_name = input_video.replace(".mp4", "")
 
 
 
 
398
  # Get the current local time
399
  t = time.localtime()
400
- # Format the time as a string
401
  current_time = time.strftime("%H:%M:%S", t)
402
  print("Current Time =", current_time)
 
403
  segments = transcribe(audio=input_audio)
404
  language = "fa"
405
  subtitle_file = generate_subtitle_file(language=language, segments=segments, input_video_name=input_video_name)
@@ -408,31 +325,24 @@ def process_video(url, type):
408
  srt_string = read_srt_file(subtitle_file)
409
  google_translate = translate_text(api_key, source_language, target_language, srt_string)
410
  write_google(google_translate)
 
 
411
  video = VideoFileClip(input_video)
412
- audio = AudioFileClip(input_audio)
413
- video = video.with_audio(audio)
414
- print(video)
415
  subtitles = pysrt.open("google_translate.srt", encoding="utf-8")
416
  output_video_file = input_video_name + '_subtitled' + ".mp4"
417
  subtitle_clips = create_subtitle_clips(subtitles, video.size, 24, 'arial.ttf', 'yellow', False)
418
  final_video = CompositeVideoClip([video] + subtitle_clips)
419
  final_video.write_videofile(output_video_file, codec="libx264", audio_codec="aac", logger=None)
420
  video.close()
421
- audio.close()
422
  print('final')
 
423
  # Get the current local time
424
  t = time.localtime()
425
-
426
- # Format the time as a string
427
  current_time = time.strftime("%H:%M:%S", t)
428
  print("Current Time =", current_time)
429
-
430
- # Generate the URL for the file
431
- return output_video_file
432
 
433
- def download_file(file_path):
434
- return gr.File.update(file_path)
435
 
436
- iface = gr.Interface(fn=process_video, inputs=[gr.Text(),gr.Dropdown(["insta","youtube"])], outputs="file")
437
 
438
  iface.launch(debug=True)
 
7
  from faster_whisper import WhisperModel
8
  import requests
9
  import json
10
+ import arabic_reshaper # pip install arabic-reshaper
11
+ from bidi.algorithm import get_display # pip install python-bidi
12
  from moviepy import VideoFileClip, TextClip, CompositeVideoClip, AudioFileClip, ImageClip
13
  import pysrt
14
  import instaloader
 
17
  import re
18
  from io import BytesIO
19
  from PIL import Image
20
+ import yt_dlp
21
+ import os
 
22
 
23
+ api_key = "268976:66f4f58a2a905"
24
 
25
  def fetch_data(url):
26
  try:
 
70
  def download_file_in_parallel(link, size, num_threads=4):
71
  url = link.split("#")[0]
72
  filename = link.split("#")[1]
73
+ print(url + " filename: " + filename)
74
  response = requests.head(url)
75
+ # file_size = int(response.headers['Content-Length'])
76
  chunk_size = size // num_threads
77
 
78
  ranges = [(i * chunk_size, (i + 1) * chunk_size - 1) for i in range(num_threads)]
 
89
  merge_files(filename, num_threads)
90
  print(f'Downloaded successfully: {filename}')
91
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
92
  def insta_oneapi(url, api_key):
93
  shortcode = url.split("/")[-2]
94
  print(shortcode)
95
+ url_one = "https://api.one-api.ir/instagram/v1/post/?shortcode=" + shortcode
96
+ request_body = [{"shortcode": shortcode}, ]
97
  headers = {"one-api-token": api_key, "Content-Type": "application/json"}
98
  response = requests.get(url_one, headers=headers)
99
  print(response)
100
  if response.status_code == 200:
 
101
  result = response.json()
102
  try:
103
  time.sleep(10)
 
109
  file.write(chunk)
110
  file.close()
111
  print(f"Downloaded successfully")
112
+ image_url = result["result"]['media'][0]["cover"]
113
  image_file_path = download_image(image_url)
114
  return "video.mp4", image_file_path
115
  except requests.exceptions.RequestException as e:
 
118
  print(f"Error: {response.status_code}, {response.text}")
119
  return None
120
 
121
+ def download_image(url, save_path='downloaded_image.jpg'):
122
+ response = requests.get(url)
123
+ image = Image.open(BytesIO(response.content))
124
+ image.save(save_path)
125
+ return save_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
 
127
  def extract_audio(input_video_name):
128
  # Define the input video file and output audio file
 
168
  for index, segment in enumerate(segments):
169
  segment_start = format_time(segment.start)
170
  segment_end = format_time(segment.end)
171
+ text += f"{str(index + 1)} \n"
172
  text += f"{segment_start} --> {segment_end} \n"
173
  text += f"{segment.text} \n"
174
  text += "\n"
 
202
  request_body = [{
203
  "role": "user",
204
  "content": f"{text} ROLE: Expert translator for Persian motivational anime subtitles. TASK: Translate input English SRT (`[X.XXs -> Y.YYs] English text`) to Persian SRT. REQUIREMENTS: 1. STRICT FORMAT: Output MUST be `[X.XXs -> Y.YYs] Persian Text` per line. 2. TIMESTAMPS: CRITICAL - NEVER change timestamps; copy EXACTLY. 3. TRANSLATION: Create motivational, touching, natural, understandable Persian; capture spirit, avoid literalism. 4. LENGTH: Ensure Persian text is concise & readable in time. AVOID: Format errors, timestamp changes, unnatural translation, overly long text. in respose dont add any thing exept for the srt formated translation.Now translate:"
205
+ }, ]
206
 
207
  # Add the API key to the request
208
  headers = {
 
250
  def create_subtitle_clips(subtitles, videosize, fontsize, font, color, debug):
251
  subtitle_clips = []
252
  for subtitle in subtitles:
253
+ start_time = time_to_seconds(subtitle.start) # Add 2 seconds offset
254
  end_time = time_to_seconds(subtitle.end)
255
  duration = end_time - start_time
256
  video_width, video_height = videosize
257
+ max_width = video_width * 0.8
258
  max_height = video_height * 0.2
259
+ # reshaped_text = arabic_reshaper.reshape(subtitle.text)
260
+ # bidi_text = get_display(reshaped_text)
261
+ text_clip = TextClip(font, subtitle.text, font_size=fontsize, size=(int(video_width * 0.8), int(video_height * 0.2)),
262
+ text_align="center", color=color, method='caption').with_start(start_time).with_duration(duration)
263
  subtitle_x_position = 'center'
264
  subtitle_y_position = video_height * 0.68
265
  text_position = (subtitle_x_position, subtitle_y_position)
266
  subtitle_clips.append(text_clip.with_position(text_position))
267
  return subtitle_clips
268
 
269
+ def download_youtube(url, save_path):
270
+ """
271
+ Downloads a YouTube video to the specified save path using yt_dlp.
272
 
273
+ Args:
274
+ url (str): The URL of the YouTube video to download.
275
+ save_path (str): The directory where the video will be saved.
276
 
277
+ Returns:
278
+ str: The full path to the downloaded video file.
279
+ """
280
+ ydl_opts = {
281
+ 'format': 'best', # Downloads the best quality format with both video and audio
282
+ 'outtmpl': os.path.join(save_path, '%(title)s.%(ext)s'), # Saves with title and extension
283
+ }
284
+ try:
285
+ with yt_dlp.YoutubeDL(ydl_opts) as ydl:
286
+ # Get video info without downloading to determine the file name
287
+ info = ydl.extract_info(url, download=False)
288
+ file_path = ydl.prepare_filename(info)
289
+ # Download the video
290
+ ydl.download([url])
291
+ print(f'Video downloaded successfully to {file_path}')
292
+ return file_path
293
+ except Exception as e:
294
+ print(f"Error downloading video: {e}")
295
+ return None
296
 
297
+ def process_video(url, type):
298
+ if type == "insta":
299
+ input_video, image_path = insta_oneapi(url, api_key)
300
  input_video_name = input_video.replace(".mp4", "")
301
  video = VideoFileClip(input_video)
302
  image_clip = ImageClip(image_path).with_duration(1)
 
303
  image_clip = image_clip.with_position(("center", "center")).resized(height=video.size[1])
304
  first_video = CompositeVideoClip([video.with_start(1), image_clip])
305
+ input_video = input_video_name + "_cover.mp4"
 
306
  first_video.write_videofile(input_video, codec="libx264", audio_codec="aac", logger=None)
307
  input_audio = extract_audio(input_video)
308
+ elif type == "youtube":
309
+ input_video = download_youtube(url, ".")
310
+ if input_video is None:
311
+ raise ValueError("Failed to download YouTube video")
312
+ input_audio = extract_audio(input_video)
313
+ input_video_name = os.path.splitext(input_video)[0]
314
+
315
  # Get the current local time
316
  t = time.localtime()
 
317
  current_time = time.strftime("%H:%M:%S", t)
318
  print("Current Time =", current_time)
319
+
320
  segments = transcribe(audio=input_audio)
321
  language = "fa"
322
  subtitle_file = generate_subtitle_file(language=language, segments=segments, input_video_name=input_video_name)
 
325
  srt_string = read_srt_file(subtitle_file)
326
  google_translate = translate_text(api_key, source_language, target_language, srt_string)
327
  write_google(google_translate)
328
+
329
+ # Load the video, which already has audio
330
  video = VideoFileClip(input_video)
 
 
 
331
  subtitles = pysrt.open("google_translate.srt", encoding="utf-8")
332
  output_video_file = input_video_name + '_subtitled' + ".mp4"
333
  subtitle_clips = create_subtitle_clips(subtitles, video.size, 24, 'arial.ttf', 'yellow', False)
334
  final_video = CompositeVideoClip([video] + subtitle_clips)
335
  final_video.write_videofile(output_video_file, codec="libx264", audio_codec="aac", logger=None)
336
  video.close()
 
337
  print('final')
338
+
339
  # Get the current local time
340
  t = time.localtime()
 
 
341
  current_time = time.strftime("%H:%M:%S", t)
342
  print("Current Time =", current_time)
 
 
 
343
 
344
+ return output_video_file
 
345
 
346
+ iface = gr.Interface(fn=process_video, inputs=[gr.Text(), gr.Dropdown(["insta", "youtube"])], outputs="file")
347
 
348
  iface.launch(debug=True)