Spaces:
Running
Running
Fix YouTube API initialization race condition on simulation switch
Browse files- app.py +17 -49
- theater_template.html +14 -4
app.py
CHANGED
|
@@ -49,9 +49,9 @@ custom_simulation_store = {
|
|
| 49 |
}
|
| 50 |
|
| 51 |
def play_simulation_selection(selection: str) -> str:
|
| 52 |
-
if selection == "Steve Jobs
|
| 53 |
return get_demo_html()
|
| 54 |
-
elif selection == "Carl Sagan
|
| 55 |
return get_demo_2_html()
|
| 56 |
elif selection == "My Custom Simulation":
|
| 57 |
if custom_simulation_store["video_id"] and custom_simulation_store["chat_data"]:
|
|
@@ -61,63 +61,31 @@ def play_simulation_selection(selection: str) -> str:
|
|
| 61 |
return ""
|
| 62 |
|
| 63 |
def handle_generation(yt_url: str, pdf_file, doc_text: str, srt_text: str, hf_token: str):
|
| 64 |
-
# 1.
|
| 65 |
video_id = extract_youtube_video_id(yt_url)
|
| 66 |
-
|
| 67 |
-
# Fallback 1: Extract from the uploaded PDF/text filename if yt_url is empty
|
| 68 |
-
if not video_id and pdf_file is not None:
|
| 69 |
-
filename = os.path.basename(pdf_file.name)
|
| 70 |
-
video_id = extract_youtube_video_id(filename)
|
| 71 |
-
|
| 72 |
-
# Fallback 2: Extract from the SRT text content (first 5 lines) if still empty
|
| 73 |
-
if not video_id and srt_text:
|
| 74 |
-
lines = srt_text.split('\n')[:5]
|
| 75 |
-
for line in lines:
|
| 76 |
-
extracted = extract_youtube_video_id(line)
|
| 77 |
-
if extracted:
|
| 78 |
-
video_id = extracted
|
| 79 |
-
break
|
| 80 |
-
|
| 81 |
if not video_id:
|
| 82 |
return (
|
| 83 |
gr.update(),
|
| 84 |
-
"### ❌ Error\nInvalid YouTube URL. Please provide a valid YouTube link or 11-character Video ID
|
| 85 |
gr.update()
|
| 86 |
)
|
| 87 |
|
| 88 |
-
# 2. Identify Document Source
|
| 89 |
doc_path = None
|
| 90 |
document_content = None
|
| 91 |
-
manual_transcript = None
|
| 92 |
-
|
| 93 |
-
# Check if the uploaded file is actually an SRT transcript
|
| 94 |
-
uploaded_as_srt = False
|
| 95 |
if pdf_file is not None:
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
|
| 99 |
-
|
| 100 |
-
if uploaded_as_srt:
|
| 101 |
-
# Read the uploaded SRT file as the manual transcript
|
| 102 |
-
with open(pdf_file.name, "r", encoding="utf-8") as f:
|
| 103 |
-
manual_transcript = f.read()
|
| 104 |
-
# If no separate reference document is pasted, default to using the transcript itself
|
| 105 |
-
if doc_text.strip():
|
| 106 |
-
document_content = doc_text.strip()
|
| 107 |
-
else:
|
| 108 |
-
document_content = manual_transcript
|
| 109 |
else:
|
| 110 |
-
|
| 111 |
-
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
gr.update()
|
| 119 |
-
)
|
| 120 |
-
manual_transcript = srt_text.strip() if srt_text.strip() else None
|
| 121 |
|
| 122 |
# 4. Use provided token or default token
|
| 123 |
token = hf_token.strip() if hf_token.strip() else DEFAULT_HF_TOKEN
|
|
@@ -330,7 +298,7 @@ with gr.Blocks(title="ReLiveStream - Interactive Replay", theme=custom_theme, cs
|
|
| 330 |
|
| 331 |
pdf_input = gr.File(
|
| 332 |
label="Upload Reference PDF/Text",
|
| 333 |
-
file_types=[".pdf", ".txt"
|
| 334 |
file_count="single"
|
| 335 |
)
|
| 336 |
|
|
|
|
| 49 |
}
|
| 50 |
|
| 51 |
def play_simulation_selection(selection: str) -> str:
|
| 52 |
+
if selection == "Steve Jobs 1983 Speech (Demo)":
|
| 53 |
return get_demo_html()
|
| 54 |
+
elif selection == "Carl Sagan Demon-Haunted World (Demo)":
|
| 55 |
return get_demo_2_html()
|
| 56 |
elif selection == "My Custom Simulation":
|
| 57 |
if custom_simulation_store["video_id"] and custom_simulation_store["chat_data"]:
|
|
|
|
| 61 |
return ""
|
| 62 |
|
| 63 |
def handle_generation(yt_url: str, pdf_file, doc_text: str, srt_text: str, hf_token: str):
|
| 64 |
+
# 1. Validate YouTube Link
|
| 65 |
video_id = extract_youtube_video_id(yt_url)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 66 |
if not video_id:
|
| 67 |
return (
|
| 68 |
gr.update(),
|
| 69 |
+
"### ❌ Error\nInvalid YouTube URL. Please provide a valid YouTube link or 11-character Video ID.",
|
| 70 |
gr.update()
|
| 71 |
)
|
| 72 |
|
| 73 |
+
# 2. Identify Document Source
|
| 74 |
doc_path = None
|
| 75 |
document_content = None
|
|
|
|
|
|
|
|
|
|
|
|
|
| 76 |
if pdf_file is not None:
|
| 77 |
+
doc_path = pdf_file.name
|
| 78 |
+
elif doc_text.strip():
|
| 79 |
+
document_content = doc_text.strip()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 80 |
else:
|
| 81 |
+
return (
|
| 82 |
+
gr.update(),
|
| 83 |
+
"### ❌ Error\nPlease upload a PDF/text file or paste some reference document text.",
|
| 84 |
+
gr.update()
|
| 85 |
+
)
|
| 86 |
+
|
| 87 |
+
# 3. Clean manual transcript input if any
|
| 88 |
+
manual_transcript = srt_text.strip() if srt_text.strip() else None
|
|
|
|
|
|
|
|
|
|
| 89 |
|
| 90 |
# 4. Use provided token or default token
|
| 91 |
token = hf_token.strip() if hf_token.strip() else DEFAULT_HF_TOKEN
|
|
|
|
| 298 |
|
| 299 |
pdf_input = gr.File(
|
| 300 |
label="Upload Reference PDF/Text",
|
| 301 |
+
file_types=[".pdf", ".txt"],
|
| 302 |
file_count="single"
|
| 303 |
)
|
| 304 |
|
theater_template.html
CHANGED
|
@@ -317,9 +317,6 @@
|
|
| 317 |
</div>
|
| 318 |
</div>
|
| 319 |
|
| 320 |
-
<!-- YouTube IFrame API -->
|
| 321 |
-
<script src="https://www.youtube.com/iframe_api"></script>
|
| 322 |
-
|
| 323 |
<script>
|
| 324 |
// Embedded Chat Data Placeholder (Replaced by Python script)
|
| 325 |
const chatData = {{CHAT_DATA_JSON}};
|
|
@@ -482,7 +479,6 @@
|
|
| 482 |
player = new YT.Player('player', {
|
| 483 |
height: '100%',
|
| 484 |
width: '100%',
|
| 485 |
-
host: 'https://www.youtube-nocookie.com',
|
| 486 |
videoId: videoId,
|
| 487 |
playerVars: {
|
| 488 |
'playsinline': 1,
|
|
@@ -512,6 +508,20 @@
|
|
| 512 |
|
| 513 |
// Initialize
|
| 514 |
prepareMessages();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 515 |
</script>
|
| 516 |
</body>
|
| 517 |
</html>
|
|
|
|
| 317 |
</div>
|
| 318 |
</div>
|
| 319 |
|
|
|
|
|
|
|
|
|
|
| 320 |
<script>
|
| 321 |
// Embedded Chat Data Placeholder (Replaced by Python script)
|
| 322 |
const chatData = {{CHAT_DATA_JSON}};
|
|
|
|
| 479 |
player = new YT.Player('player', {
|
| 480 |
height: '100%',
|
| 481 |
width: '100%',
|
|
|
|
| 482 |
videoId: videoId,
|
| 483 |
playerVars: {
|
| 484 |
'playsinline': 1,
|
|
|
|
| 508 |
|
| 509 |
// Initialize
|
| 510 |
prepareMessages();
|
| 511 |
+
|
| 512 |
+
// Asynchronously load the YouTube IFrame Player API
|
| 513 |
+
if (window.YT && window.YT.Player) {
|
| 514 |
+
onYouTubeIframeAPIReady();
|
| 515 |
+
} else {
|
| 516 |
+
var tag = document.createElement('script');
|
| 517 |
+
tag.src = "https://www.youtube.com/iframe_api";
|
| 518 |
+
var firstScriptTag = document.getElementsByTagName('script')[0];
|
| 519 |
+
if (firstScriptTag) {
|
| 520 |
+
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
|
| 521 |
+
} else {
|
| 522 |
+
document.head.appendChild(tag);
|
| 523 |
+
}
|
| 524 |
+
}
|
| 525 |
</script>
|
| 526 |
</body>
|
| 527 |
</html>
|