| | import io |
| | import gradio as gr |
| | import torch |
| | from transformers import WhisperProcessor, WhisperForConditionalGeneration |
| | import requests |
| | from bs4 import BeautifulSoup |
| | import tempfile |
| | import os |
| | import soundfile as sf |
| | from spellchecker import SpellChecker |
| | from pydub import AudioSegment |
| | import librosa |
| |
|
| | |
| | device = "cuda" if torch.cuda.is_available() else "cpu" |
| | print(f"Using device: {device}") |
| |
|
| | |
| | model_name = "openai/whisper-small" |
| | processor = WhisperProcessor.from_pretrained(model_name) |
| | model = WhisperForConditionalGeneration.from_pretrained(model_name).to(device) |
| |
|
| | spell = SpellChecker() |
| |
|
| | def download_audio_from_url(url): |
| | try: |
| | if "share" in url: |
| | print("Processing shareable link...") |
| | response = requests.get(url) |
| | soup = BeautifulSoup(response.content, 'html.parser') |
| | video_tag = soup.find('video') |
| | if video_tag and 'src' in video_tag.attrs: |
| | video_url = video_tag['src'] |
| | print(f"Extracted video URL: {video_url}") |
| | else: |
| | raise ValueError("Direct video URL not found in the shareable link.") |
| | else: |
| | video_url = url |
| | |
| | print(f"Downloading video from URL: {video_url}") |
| | response = requests.get(video_url) |
| | audio_bytes = response.content |
| | print(f"Successfully downloaded {len(audio_bytes)} bytes of data") |
| | return audio_bytes |
| | except Exception as e: |
| | print(f"Error in download_audio_from_url: {str(e)}") |
| | raise |
| |
|
| | def correct_spelling(text): |
| | words = text.split() |
| | corrected_words = [spell.correction(word) or word for word in words] |
| | return ' '.join(corrected_words) |
| |
|
| | def format_transcript(transcript): |
| | sentences = transcript.split('.') |
| | formatted_transcript = [] |
| | current_speaker = None |
| | for sentence in sentences: |
| | if ':' in sentence: |
| | speaker, content = sentence.split(':', 1) |
| | if speaker != current_speaker: |
| | formatted_transcript.append(f"\n\n{speaker.strip()}:{content.strip()}.") |
| | current_speaker = speaker |
| | else: |
| | formatted_transcript.append(f"{content.strip()}.") |
| | else: |
| | formatted_transcript.append(sentence.strip() + '.') |
| | return ' '.join(formatted_transcript) |
| |
|
| | def transcribe_audio(audio_file): |
| | try: |
| | |
| | audio_input, _ = librosa.load(audio_file, sr=16000) |
| | |
| | |
| | audio_input = audio_input.astype(np.float32) |
| |
|
| | |
| | input_features = processor(audio_input, sampling_rate=16000, return_tensors="pt").input_features.to(device) |
| |
|
| | |
| | predicted_ids = model.generate(input_features) |
| |
|
| | |
| | transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True) |
| |
|
| | return transcription[0] |
| | except Exception as e: |
| | print(f"Error in transcribe_audio: {str(e)}") |
| | raise |
| |
|
| | def transcribe_video(url): |
| | try: |
| | print(f"Attempting to download audio from URL: {url}") |
| | audio_bytes = download_audio_from_url(url) |
| | print(f"Successfully downloaded {len(audio_bytes)} bytes of audio data") |
| | |
| | |
| | audio = AudioSegment.from_file(io.BytesIO(audio_bytes)) |
| | |
| | |
| | with tempfile.NamedTemporaryFile(delete=False, suffix=".wav") as temp_audio: |
| | audio.export(temp_audio.name, format="wav") |
| | temp_audio_path = temp_audio.name |
| |
|
| | print("Starting audio transcription...") |
| | transcript = transcribe_audio(temp_audio_path) |
| | print("Transcription completed successfully") |
| | |
| | |
| | os.unlink(temp_audio_path) |
| |
|
| | |
| | transcript = correct_spelling(transcript) |
| | transcript = format_transcript(transcript) |
| |
|
| | return transcript |
| | except Exception as e: |
| | error_message = f"An error occurred: {str(e)}" |
| | print(error_message) |
| | return error_message |
| |
|
| | def download_transcript(transcript): |
| | with tempfile.NamedTemporaryFile(mode='w', delete=False, suffix='.txt') as temp_file: |
| | temp_file.write(transcript) |
| | temp_file_path = temp_file.name |
| | return temp_file_path |
| |
|
| | |
| | with gr.Blocks(title="Video Transcription") as demo: |
| | gr.Markdown("# Video Transcription") |
| | video_url = gr.Textbox(label="Video URL") |
| | transcribe_button = gr.Button("Transcribe") |
| | transcript_output = gr.Textbox(label="Transcript", lines=20) |
| | download_button = gr.Button("Download Transcript") |
| | download_link = gr.File(label="Download Transcript") |
| | |
| | transcribe_button.click(fn=transcribe_video, inputs=video_url, outputs=transcript_output) |
| | download_button.click(fn=download_transcript, inputs=transcript_output, outputs=download_link) |
| |
|
| | demo.launch() |