Bajiyo commited on
Commit
a1b1ec8
1 Parent(s): 7ba7abe

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +86 -0
app.py ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from pytube import YouTube
2
+ from pydub import AudioSegment
3
+ import whisper
4
+ import webrtcvad
5
+ import gradio as gr
6
+ import os
7
+
8
+ def download_audio(youtube_url, download_path='downloads', audio_filename='audio.mp3'):
9
+ yt = YouTube(youtube_url)
10
+ audio_stream = yt.streams.filter(only_audio=True).first()
11
+ if not os.path.exists(download_path):
12
+ os.makedirs(download_path)
13
+ out_file = audio_stream.download(output_path=download_path, filename=audio_filename)
14
+ return out_file
15
+
16
+ def convert_to_wav(mp3_path, wav_path='downloads/audio.wav'):
17
+ audio = AudioSegment.from_file(mp3_path)
18
+ audio.export(wav_path, format='wav')
19
+ return wav_path
20
+
21
+ def transcribe_audio(audio_path):
22
+ model = whisper.load_model("base")
23
+ result = model.transcribe(audio_path)
24
+ return result["segments"]
25
+
26
+ def vad_audio(audio_path, aggressiveness=3):
27
+ audio = AudioSegment.from_wav(audio_path)
28
+ audio = audio.set_frame_rate(16000).set_channels(1)
29
+ vad = webrtcvad.Vad(aggressiveness)
30
+
31
+ def frame_generator(audio_segment, frame_duration_ms=10):
32
+ n = int(audio_segment.frame_rate * (frame_duration_ms / 1000.0) * 2) # Calculate frame size
33
+ offset = 0
34
+ while offset + n < len(audio_segment.raw_data):
35
+ yield audio_segment.raw_data[offset:offset + n]
36
+ offset += n
37
+
38
+ frames = frame_generator(audio)
39
+ segments = []
40
+ chunk_start = None
41
+ timestamp = 0.0
42
+
43
+ for frame in frames:
44
+ is_speech = vad.is_speech(frame, sample_rate=16000)
45
+ if is_speech:
46
+ if chunk_start is None:
47
+ chunk_start = timestamp
48
+ else:
49
+ if chunk_start is not None:
50
+ segments.append((chunk_start, timestamp))
51
+ chunk_start = None
52
+ timestamp += 0.01
53
+
54
+ if chunk_start is not None:
55
+ segments.append((chunk_start, timestamp))
56
+
57
+ return segments
58
+
59
+ def semantic_chunking(transcription_segments, vad_segments, max_duration=15.0):
60
+ chunks = []
61
+ chunk_id = 0
62
+ for i, (start, end) in enumerate(vad_segments):
63
+ segment_texts = [seg['text'] for seg in transcription_segments if seg['start'] >= start and seg['end'] <= end]
64
+ segment_text = ' '.join(segment_texts)
65
+ duration = end - start
66
+ if duration <= max_duration:
67
+ chunks.append({
68
+ "chunk_id": chunk_id,
69
+ "chunk_length": duration,
70
+ "text": segment_text,
71
+ "start_time": start,
72
+ "end_time": end,
73
+ })
74
+ chunk_id += 1
75
+ return chunks
76
+
77
+ def process_video(youtube_url):
78
+ mp3_path = download_audio(youtube_url)
79
+ audio_path = convert_to_wav(mp3_path)
80
+ transcription_segments = transcribe_audio(audio_path)
81
+ vad_segments = vad_audio(audio_path)
82
+ chunks = semantic_chunking(transcription_segments, vad_segments)
83
+ return chunks
84
+
85
+ iface = gr.Interface(fn=process_video, inputs="text", outputs="json", title="Semantic Chunking of YouTube Video", description="Enter a YouTube URL to get semantic chunks of the video.")
86
+ iface.launch()