Ahmadkhan12 commited on
Commit
42d0c70
·
verified ·
1 Parent(s): bf0cb55

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +87 -118
app.py CHANGED
@@ -2,176 +2,145 @@ import os
2
  import subprocess
3
  import requests
4
  import gradio as gr
5
- import srt
6
  import datetime
7
  from googletrans import Translator
8
 
9
- # -----------------------
10
- # Load HF Token safely
11
- # -----------------------
12
- HF_TOKEN = os.environ.get("HF_TOKEN")
13
- HF_STT_MODEL = "openai/whisper-small"
14
 
15
  translator = Translator()
16
 
17
- # -----------------------
18
- # FFmpeg helpers
19
- # -----------------------
20
- def extract_audio(video_path, out_audio="audio.wav"):
21
  cmd = [
22
- "ffmpeg", "-y", "-i", str(video_path),
23
- "-vn", "-ac", "1", "-ar", "16000", "-f", "wav", out_audio
 
24
  ]
25
- proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
26
- if proc.returncode != 0:
27
- raise RuntimeError(proc.stderr.decode())
28
- return out_audio
29
 
30
- def get_audio_duration(path):
 
 
 
31
  cmd = [
32
  "ffprobe", "-v", "error", "-show_entries",
33
  "format=duration", "-of",
34
  "default=noprint_wrappers=1:nokey=1", path
35
  ]
36
- proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
37
- if proc.returncode != 0:
38
- return None
39
  try:
40
- return float(proc.stdout.decode().strip())
41
  except:
42
- return None
43
 
44
- # -----------------------
45
- # HF API Call
46
- # -----------------------
47
- def hf_asr_transcribe(audio_file_path, model=HF_STT_MODEL, hf_token=HF_TOKEN):
48
- if not hf_token:
49
- raise RuntimeError("HF_TOKEN missing! Add it in your Space settings.")
50
 
51
- url = f"https://api-inference.huggingface.co/models/{model}"
52
- headers = {"Authorization": f"Bearer {hf_token}"}
53
 
54
- with open(audio_file_path, "rb") as f:
55
  audio_bytes = f.read()
56
 
57
- response = requests.post(url, headers=headers, data=audio_bytes, timeout=120)
 
58
 
59
- if response.status_code != 200:
60
- raise RuntimeError(f"HF API Error {response.status_code}: {response.text}")
 
61
 
62
- try:
63
- data = response.json()
64
- except:
65
- return response.text
66
-
67
- if isinstance(data, dict) and "text" in data:
68
- return data["text"]
69
-
70
- if isinstance(data, list):
71
- texts = []
72
- for item in data:
73
- if isinstance(item, dict) and "text" in item:
74
- texts.append(item["text"])
75
- if texts:
76
- return " ".join(texts)
77
-
78
- return str(data)
79
-
80
- # -----------------------
81
- # Generate SRT
82
- # -----------------------
83
- def transcript_to_srt(transcript, duration_seconds, avg_segment_len=4.0):
84
- words = transcript.strip().split()
85
  if not words:
86
  return ""
87
 
88
- if duration_seconds and duration_seconds > 0:
89
- wps = len(words) / duration_seconds
90
- else:
91
- wps = 2.5
 
 
 
 
92
 
93
- words_per_segment = max(1, int(round(wps * avg_segment_len)))
94
- segments = []
95
- seg_index = 1
96
- idx = 0
97
- current_time = 0.0
98
 
99
- while idx < len(words):
100
- chunk = words[idx: idx + words_per_segment]
101
- text = " ".join(chunk)
 
 
 
 
 
102
 
103
- start = datetime.timedelta(seconds=current_time)
104
- end = datetime.timedelta(seconds=current_time + (len(chunk) / wps))
 
 
105
 
106
- segments.append(
107
- srt.Subtitle(
108
- index=seg_index,
109
- start=start,
110
- end=end,
111
- content=text
112
- )
113
- )
114
 
115
- seg_index += 1
116
- idx += words_per_segment
117
- current_time += len(chunk) / wps
118
 
119
- return srt.compose(segments)
120
 
121
- # -----------------------
122
- # Main Function
123
- # -----------------------
124
- def process_video(video_file, target_lang):
125
- audio_path = "audio.wav"
126
- extract_audio(video_file, audio_path)
127
- duration = get_audio_duration(audio_path) or 0.0
128
 
129
- transcript = hf_asr_transcribe(audio_path)
130
 
131
- if target_lang != "original":
132
- try:
133
- transcript = translator.translate(transcript, dest=target_lang).text
134
- except:
135
- pass
136
 
137
- srt_text = transcript_to_srt(transcript, duration)
138
- srt_path = "subtitles.srt"
139
 
140
- with open(srt_path, "w", encoding="utf-8") as f:
141
- f.write(srt_text)
 
142
 
143
- return srt_path
144
 
145
- # -----------------------
146
  # Gradio UI
147
- # -----------------------
148
  languages = {
149
- "original": "No translation",
150
  "en": "English",
151
  "ur": "Urdu",
152
  "hi": "Hindi",
153
  "ps": "Pashto",
154
- "ar": "Arabic",
155
  }
156
 
157
- def gradio_process(video, lang):
158
- if video is None:
159
- return None
160
- try:
161
- return process_video(video, lang)
162
- except Exception as e:
163
- raise gr.Error(str(e))
164
-
165
  demo = gr.Interface(
166
- fn=gradio_process,
167
  inputs=[
168
  gr.Video(label="Upload Video"),
169
  gr.Dropdown(choices=list(languages.keys()), value="original", label="Translate Into")
170
  ],
171
  outputs=gr.File(label="Download SRT"),
172
- title="AI Subtitle Generator (Hugging Face API)",
173
- description="Upload video → Auto subtitles → Optional translation → Download .srt"
174
  )
175
 
176
- if __name__ == "__main__":
177
- demo.launch()
 
2
  import subprocess
3
  import requests
4
  import gradio as gr
 
5
  import datetime
6
  from googletrans import Translator
7
 
8
+ HF_TOKEN = os.environ.get("HF_TOKEN")
9
+ HF_MODEL = "openai/whisper-small"
 
 
 
10
 
11
  translator = Translator()
12
 
13
+ # ---------------------------
14
+ # Extract audio with FFmpeg
15
+ # ---------------------------
16
+ def extract_audio(video_path, audio_out="audio.wav"):
17
  cmd = [
18
+ "ffmpeg", "-y", "-i", video_path,
19
+ "-vn", "-ac", "1", "-ar", "16000",
20
+ "-f", "wav", audio_out
21
  ]
22
+ subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
23
+ return audio_out
 
 
24
 
25
+ # ---------------------------
26
+ # Get audio duration
27
+ # ---------------------------
28
+ def get_duration(path):
29
  cmd = [
30
  "ffprobe", "-v", "error", "-show_entries",
31
  "format=duration", "-of",
32
  "default=noprint_wrappers=1:nokey=1", path
33
  ]
34
+ p = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
 
 
35
  try:
36
+ return float(p.stdout.decode().strip())
37
  except:
38
+ return 0.0
39
 
40
+ # ---------------------------
41
+ # HF API → Speech-to-text
42
+ # ---------------------------
43
+ def transcribe_audio(audio_path):
44
+ if HF_TOKEN is None:
45
+ raise RuntimeError("HF_TOKEN missing in Space settings.")
46
 
47
+ url = f"https://api-inference.huggingface.co/models/{HF_MODEL}"
48
+ headers = {"Authorization": f"Bearer {HF_TOKEN}"}
49
 
50
+ with open(audio_path, "rb") as f:
51
  audio_bytes = f.read()
52
 
53
+ r = requests.post(url, headers=headers, data=audio_bytes)
54
+ out = r.json()
55
 
56
+ if "text" in out:
57
+ return out["text"]
58
+ return ""
59
 
60
+ # ---------------------------
61
+ # Build SRT manually
62
+ # ---------------------------
63
+ def build_srt(text, duration):
64
+ words = text.split()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
65
  if not words:
66
  return ""
67
 
68
+ words_per_second = len(words) / max(duration, 1)
69
+ seg_len = 4 # seconds per subtitle segment
70
+ w_per_seg = max(1, int(seg_len * words_per_second))
71
+
72
+ srt_text = ""
73
+ start_sec = 0
74
+ index = 1
75
+ i = 0
76
 
77
+ while i < len(words):
78
+ segment_words = words[i:i + w_per_seg]
79
+ end_sec = start_sec + seg_len
 
 
80
 
81
+ start_time = str(datetime.timedelta(seconds=start_sec))
82
+ end_time = str(datetime.timedelta(seconds=end_sec))
83
+
84
+ # Ensure hh:mm:ss,ms format
85
+ if "." not in start_time:
86
+ start_time += ",000"
87
+ else:
88
+ start_time = start_time.replace(".", ",")[:12]
89
 
90
+ if "." not in end_time:
91
+ end_time += ",000"
92
+ else:
93
+ end_time = end_time.replace(".", ",")[:12]
94
 
95
+ srt_text += f"{index}\n{start_time} --> {end_time}\n{' '.join(segment_words)}\n\n"
 
 
 
 
 
 
 
96
 
97
+ start_sec = end_sec
98
+ index += 1
99
+ i += w_per_seg
100
 
101
+ return srt_text
102
 
103
+ # ---------------------------
104
+ # Master function
105
+ # ---------------------------
106
+ def process_video(video, lang):
107
+ audio_path = extract_audio(video)
108
+ duration = get_duration(audio_path)
 
109
 
110
+ text = transcribe_audio(audio_path)
111
 
112
+ if lang != "original":
113
+ text = translator.translate(text, dest=lang).text
 
 
 
114
 
115
+ srt_output = build_srt(text, duration)
 
116
 
117
+ output_path = "subtitles.srt"
118
+ with open(output_path, "w", encoding="utf-8") as f:
119
+ f.write(srt_output)
120
 
121
+ return output_path
122
 
123
+ # ---------------------------
124
  # Gradio UI
125
+ # ---------------------------
126
  languages = {
127
+ "original": "Original",
128
  "en": "English",
129
  "ur": "Urdu",
130
  "hi": "Hindi",
131
  "ps": "Pashto",
132
+ "ar": "Arabic"
133
  }
134
 
 
 
 
 
 
 
 
 
135
  demo = gr.Interface(
136
+ fn=process_video,
137
  inputs=[
138
  gr.Video(label="Upload Video"),
139
  gr.Dropdown(choices=list(languages.keys()), value="original", label="Translate Into")
140
  ],
141
  outputs=gr.File(label="Download SRT"),
142
+ title="AI Subtitle Generator",
143
+ description="Upload a video → auto subtitles → optional translation → download SRT."
144
  )
145
 
146
+ demo.launch()