Spaces:
Sleeping
Sleeping
Enhance video download functionality in Streamlit app with optional cookies support for YouTube authentication
Browse files- Dockerfile +7 -0
- src/streamlit_app.py +50 -8
Dockerfile
CHANGED
@@ -2,6 +2,11 @@ FROM python:3.9-slim
|
|
2 |
|
3 |
WORKDIR /app
|
4 |
|
|
|
|
|
|
|
|
|
|
|
5 |
# Install system dependencies including ffmpeg for audio processing
|
6 |
RUN apt-get update && apt-get install -y \
|
7 |
build-essential \
|
@@ -10,6 +15,8 @@ RUN apt-get update && apt-get install -y \
|
|
10 |
git \
|
11 |
ffmpeg \
|
12 |
libsndfile1 \
|
|
|
|
|
13 |
&& rm -rf /var/lib/apt/lists/*
|
14 |
|
15 |
# Copy requirements and install Python dependencies
|
|
|
2 |
|
3 |
WORKDIR /app
|
4 |
|
5 |
+
# Set DNS to improve network connectivity during build
|
6 |
+
# Using Google DNS servers for better reliability
|
7 |
+
RUN echo "nameserver 8.8.8.8" > /etc/resolv.conf && \
|
8 |
+
echo "nameserver 8.8.4.4" >> /etc/resolv.conf
|
9 |
+
|
10 |
# Install system dependencies including ffmpeg for audio processing
|
11 |
RUN apt-get update && apt-get install -y \
|
12 |
build-essential \
|
|
|
15 |
git \
|
16 |
ffmpeg \
|
17 |
libsndfile1 \
|
18 |
+
ca-certificates \
|
19 |
+
&& apt-get clean \
|
20 |
&& rm -rf /var/lib/apt/lists/*
|
21 |
|
22 |
# Copy requirements and install Python dependencies
|
src/streamlit_app.py
CHANGED
@@ -52,12 +52,28 @@ ENGLISH_ACCENTS = {
|
|
52 |
"en-caribbean": "Caribbean English",
|
53 |
}
|
54 |
|
55 |
-
def download_video(url, video_path="video.mp4"):
|
56 |
"""Download a video from a URL"""
|
57 |
-
ydl_opts = {
|
58 |
-
|
59 |
-
|
60 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
|
62 |
def extract_audio(video_path="video.mp4", audio_path="audio.wav"):
|
63 |
"""Extract audio from video file using ffmpeg"""
|
@@ -268,6 +284,31 @@ tab1, tab2 = st.tabs(["Video URL", "Upload Audio"])
|
|
268 |
with tab1:
|
269 |
url = st.text_input("Enter a public video URL (e.g. Loom, YouTube, or direct MP4 link)")
|
270 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
271 |
if st.button("Analyze Video"):
|
272 |
if not url:
|
273 |
st.warning("Please enter a valid URL")
|
@@ -283,7 +324,7 @@ with tab1:
|
|
283 |
|
284 |
# Download and process the video
|
285 |
status.text("Downloading video...")
|
286 |
-
download_success = download_video(url, video_path)
|
287 |
if not download_success:
|
288 |
st.error("Failed to download video")
|
289 |
else:
|
@@ -318,13 +359,14 @@ with tab1:
|
|
318 |
|
319 |
# Show audio playback
|
320 |
st.audio(audio_path)
|
321 |
-
|
322 |
-
# Clean up files
|
323 |
try:
|
324 |
if os.path.exists(video_path):
|
325 |
os.remove(video_path)
|
326 |
if os.path.exists(audio_path):
|
327 |
os.remove(audio_path)
|
|
|
|
|
328 |
except Exception as e:
|
329 |
st.warning(f"Couldn't clean up temporary files: {str(e)}")
|
330 |
|
|
|
52 |
"en-caribbean": "Caribbean English",
|
53 |
}
|
54 |
|
55 |
+
def download_video(url, video_path="video.mp4", cookies_file=None):
|
56 |
"""Download a video from a URL"""
|
57 |
+
ydl_opts = {
|
58 |
+
"outtmpl": video_path,
|
59 |
+
}
|
60 |
+
|
61 |
+
# Try to use provided cookies file first if it exists
|
62 |
+
if cookies_file and os.path.exists(cookies_file):
|
63 |
+
ydl_opts["cookiefile"] = cookies_file
|
64 |
+
else:
|
65 |
+
# Fall back to browser cookies
|
66 |
+
ydl_opts["cookiesfrombrowser"] = ("chrome",)
|
67 |
+
|
68 |
+
try:
|
69 |
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
70 |
+
ydl.download([url])
|
71 |
+
return os.path.exists(video_path)
|
72 |
+
except Exception as e:
|
73 |
+
st.error(f"Download error: {str(e)}")
|
74 |
+
if "youtube" in url.lower() and "bot" in str(e).lower():
|
75 |
+
st.warning("YouTube is requesting authentication. Please see the 'Having trouble with YouTube videos?' section for help.")
|
76 |
+
return False
|
77 |
|
78 |
def extract_audio(video_path="video.mp4", audio_path="audio.wav"):
|
79 |
"""Extract audio from video file using ffmpeg"""
|
|
|
284 |
with tab1:
|
285 |
url = st.text_input("Enter a public video URL (e.g. Loom, YouTube, or direct MP4 link)")
|
286 |
|
287 |
+
# Add file uploader for cookies.txt
|
288 |
+
cookies_file = None
|
289 |
+
uploaded_cookies = st.file_uploader("Optional: Upload cookies.txt for YouTube authentication", type="txt", help="Only needed if you have issues with YouTube videos")
|
290 |
+
|
291 |
+
if uploaded_cookies is not None:
|
292 |
+
# Save the uploaded cookies file to a temporary file
|
293 |
+
cookies_file = f"cookies_{int(time.time())}.txt"
|
294 |
+
with open(cookies_file, "wb") as f:
|
295 |
+
f.write(uploaded_cookies.getbuffer())
|
296 |
+
|
297 |
+
with st.expander("Having trouble with YouTube videos?"):
|
298 |
+
st.markdown("""
|
299 |
+
**YouTube Authentication Issues**
|
300 |
+
|
301 |
+
YouTube sometimes requires authentication to verify you're not a bot. If you encounter errors while analyzing YouTube videos, try these solutions:
|
302 |
+
|
303 |
+
1. **Use a different video source**: Try Loom or a direct MP4 link instead
|
304 |
+
2. **Export cookies from your browser**:
|
305 |
+
- Install the [cookies.txt extension](https://chrome.google.com/webstore/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc) for Chrome
|
306 |
+
- Visit YouTube and login
|
307 |
+
- Use the extension to export your cookies to a file
|
308 |
+
- Place the cookies file in the app's directory
|
309 |
+
3. **Try a shorter video**: YouTube may be less likely to require authentication for shorter clips
|
310 |
+
""")
|
311 |
+
|
312 |
if st.button("Analyze Video"):
|
313 |
if not url:
|
314 |
st.warning("Please enter a valid URL")
|
|
|
324 |
|
325 |
# Download and process the video
|
326 |
status.text("Downloading video...")
|
327 |
+
download_success = download_video(url, video_path, cookies_file)
|
328 |
if not download_success:
|
329 |
st.error("Failed to download video")
|
330 |
else:
|
|
|
359 |
|
360 |
# Show audio playback
|
361 |
st.audio(audio_path)
|
362 |
+
# Clean up files
|
|
|
363 |
try:
|
364 |
if os.path.exists(video_path):
|
365 |
os.remove(video_path)
|
366 |
if os.path.exists(audio_path):
|
367 |
os.remove(audio_path)
|
368 |
+
if cookies_file and os.path.exists(cookies_file):
|
369 |
+
os.remove(cookies_file)
|
370 |
except Exception as e:
|
371 |
st.warning(f"Couldn't clean up temporary files: {str(e)}")
|
372 |
|