Update app.py
Browse files
app.py
CHANGED
|
@@ -9,7 +9,28 @@ import os
|
|
| 9 |
import tempfile
|
| 10 |
import chromadb
|
| 11 |
|
| 12 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 13 |
chroma_client = chromadb.Client()
|
| 14 |
collection_name = "subtitle_chunks"
|
| 15 |
|
|
@@ -22,7 +43,7 @@ def extract_audio(video_file, audio_file):
|
|
| 22 |
output_file = ffmpeg.output(input_file, audio_file, **{'vn': None, 'ar': 16000, 'ac': 1, 'f': 'wav'})
|
| 23 |
ffmpeg.run(output_file)
|
| 24 |
|
| 25 |
-
# Function to transcribe audio using
|
| 26 |
def transcribe_audio(audio_file):
|
| 27 |
result = whisper_model(audio_file)
|
| 28 |
return result['text']
|
|
@@ -41,7 +62,7 @@ def split_csv(csv_path, chunk_size=50000):
|
|
| 41 |
chunks.append(chunk_file)
|
| 42 |
return chunks
|
| 43 |
|
| 44 |
-
#
|
| 45 |
def store_chunks_in_chroma(chunk_files):
|
| 46 |
collection = chroma_client.create_collection(name=collection_name)
|
| 47 |
|
|
@@ -58,7 +79,7 @@ def store_chunks_in_chroma(chunk_files):
|
|
| 58 |
ids=[f"{chunk_file}_{idx}"]
|
| 59 |
)
|
| 60 |
|
| 61 |
-
#
|
| 62 |
def search_in_chroma(transcribed_text, top_k=10):
|
| 63 |
query_embedding = generate_embedding(transcribed_text)
|
| 64 |
collection = chroma_client.get_collection(name=collection_name)
|
|
@@ -77,12 +98,27 @@ def search_in_chroma(transcribed_text, top_k=10):
|
|
| 77 |
# Streamlit UI
|
| 78 |
st.title("🎥 Video Subtitle Search with Hugging Face Whisper + Chroma DB")
|
| 79 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
# Upload video
|
| 81 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 82 |
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_video:
|
| 85 |
-
temp_video.write(
|
| 86 |
video_path = temp_video.name
|
| 87 |
|
| 88 |
audio_path = "temp_audio.wav"
|
|
@@ -96,10 +132,9 @@ if uploaded_file:
|
|
| 96 |
transcribed_text = transcribe_audio(audio_path)
|
| 97 |
st.text_area("Transcribed Text", transcribed_text, height=150)
|
| 98 |
|
| 99 |
-
# Split the
|
| 100 |
-
st.info("Splitting
|
| 101 |
-
|
| 102 |
-
chunk_files = split_csv(subtitle_db_path, chunk_size=50000)
|
| 103 |
|
| 104 |
# Store chunks in Chroma DB
|
| 105 |
st.info("Storing subtitle chunks in Chroma DB...")
|
|
@@ -122,7 +157,11 @@ if uploaded_file:
|
|
| 122 |
# Cleanup
|
| 123 |
os.remove(video_path)
|
| 124 |
os.remove(audio_path)
|
|
|
|
| 125 |
|
| 126 |
# Remove chunk files
|
| 127 |
for chunk_file in chunk_files:
|
| 128 |
os.remove(chunk_file)
|
|
|
|
|
|
|
|
|
|
|
|
| 9 |
import tempfile
|
| 10 |
import chromadb
|
| 11 |
|
| 12 |
+
# ✅ Chunked Upload Config (50 MB chunks to bypass 200 MB limit)
|
| 13 |
+
MAX_CHUNK_SIZE = 50 * 1024 * 1024 # 50 MB
|
| 14 |
+
|
| 15 |
+
def upload_file_in_chunks(file):
|
| 16 |
+
"""Split file into 50 MB chunks to bypass the 200 MB limit."""
|
| 17 |
+
chunk_list = []
|
| 18 |
+
bytes_data = file.read()
|
| 19 |
+
total_size = len(bytes_data)
|
| 20 |
+
num_chunks = (total_size // MAX_CHUNK_SIZE) + 1
|
| 21 |
+
|
| 22 |
+
st.write(f"🔹 Splitting into {num_chunks} chunks...")
|
| 23 |
+
|
| 24 |
+
for i in range(num_chunks):
|
| 25 |
+
start = i * MAX_CHUNK_SIZE
|
| 26 |
+
end = min((i + 1) * MAX_CHUNK_SIZE, total_size)
|
| 27 |
+
chunk_list.append(bytes_data[start:end])
|
| 28 |
+
|
| 29 |
+
# Combine all chunks into a single CSV
|
| 30 |
+
full_csv_data = b"".join(chunk_list)
|
| 31 |
+
return full_csv_data
|
| 32 |
+
|
| 33 |
+
# Initialize Chroma DB
|
| 34 |
chroma_client = chromadb.Client()
|
| 35 |
collection_name = "subtitle_chunks"
|
| 36 |
|
|
|
|
| 43 |
output_file = ffmpeg.output(input_file, audio_file, **{'vn': None, 'ar': 16000, 'ac': 1, 'f': 'wav'})
|
| 44 |
ffmpeg.run(output_file)
|
| 45 |
|
| 46 |
+
# Function to transcribe audio using Whisper
|
| 47 |
def transcribe_audio(audio_file):
|
| 48 |
result = whisper_model(audio_file)
|
| 49 |
return result['text']
|
|
|
|
| 62 |
chunks.append(chunk_file)
|
| 63 |
return chunks
|
| 64 |
|
| 65 |
+
# Store subtitle chunks in Chroma DB
|
| 66 |
def store_chunks_in_chroma(chunk_files):
|
| 67 |
collection = chroma_client.create_collection(name=collection_name)
|
| 68 |
|
|
|
|
| 79 |
ids=[f"{chunk_file}_{idx}"]
|
| 80 |
)
|
| 81 |
|
| 82 |
+
# Search subtitles in Chroma DB
|
| 83 |
def search_in_chroma(transcribed_text, top_k=10):
|
| 84 |
query_embedding = generate_embedding(transcribed_text)
|
| 85 |
collection = chroma_client.get_collection(name=collection_name)
|
|
|
|
| 98 |
# Streamlit UI
|
| 99 |
st.title("🎥 Video Subtitle Search with Hugging Face Whisper + Chroma DB")
|
| 100 |
|
| 101 |
+
# Sidebar for CSV Upload with Chunking
|
| 102 |
+
st.sidebar.header("📁 Upload Subtitle Database")
|
| 103 |
+
csv_file = st.sidebar.file_uploader("Upload Subtitle CSV (200 MB+ supported)", type=["csv"])
|
| 104 |
+
|
| 105 |
# Upload video
|
| 106 |
+
uploaded_video = st.file_uploader("Upload a video", type=["mp4", "avi", "mov", "mkv"])
|
| 107 |
+
|
| 108 |
+
# If both CSV and video are uploaded
|
| 109 |
+
if csv_file and uploaded_video:
|
| 110 |
+
# Handle large CSV upload using 50 MB chunks
|
| 111 |
+
st.info("Uploading CSV in 50 MB chunks...")
|
| 112 |
+
full_csv_data = upload_file_in_chunks(csv_file)
|
| 113 |
|
| 114 |
+
# Save CSV locally
|
| 115 |
+
with tempfile.NamedTemporaryFile(delete=False, suffix=".csv") as temp_csv:
|
| 116 |
+
temp_csv.write(full_csv_data)
|
| 117 |
+
csv_path = temp_csv.name
|
| 118 |
+
|
| 119 |
+
# Save video locally
|
| 120 |
with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as temp_video:
|
| 121 |
+
temp_video.write(uploaded_video.getbuffer())
|
| 122 |
video_path = temp_video.name
|
| 123 |
|
| 124 |
audio_path = "temp_audio.wav"
|
|
|
|
| 132 |
transcribed_text = transcribe_audio(audio_path)
|
| 133 |
st.text_area("Transcribed Text", transcribed_text, height=150)
|
| 134 |
|
| 135 |
+
# Split the CSV database into smaller chunks
|
| 136 |
+
st.info("Splitting CSV into smaller chunks...")
|
| 137 |
+
chunk_files = split_csv(csv_path, chunk_size=50000)
|
|
|
|
| 138 |
|
| 139 |
# Store chunks in Chroma DB
|
| 140 |
st.info("Storing subtitle chunks in Chroma DB...")
|
|
|
|
| 157 |
# Cleanup
|
| 158 |
os.remove(video_path)
|
| 159 |
os.remove(audio_path)
|
| 160 |
+
os.remove(csv_path)
|
| 161 |
|
| 162 |
# Remove chunk files
|
| 163 |
for chunk_file in chunk_files:
|
| 164 |
os.remove(chunk_file)
|
| 165 |
+
|
| 166 |
+
else:
|
| 167 |
+
st.warning("Please upload both a video file and a CSV file to proceed.")
|