Skip to content

Commit dabe2f4

Browse files
authored
Forces program to wait if there is a current thread playing a video, to ensure the previous thread stops before starting a new one (#68)
* Forces program to wait if there is a current thread playing a video, to ensure the previous thread stops before starting a new one cache play button takes 5s to reload, and stream just pauses while playing the new audio. Also there are some errors in the logs that I haven't looked at yet. * fixed UI some UI changes Search bar still shows when you press play, and buttons in cache menu no longer take 5 seconds to display submit. There are some issues in line 348 in server.py which I don't quite understand * some whitespace fixes * get rid of error statement The platform works as long as you don't try to spam out videos, or if you try to use it on bad wifi. If you do, it may lead the stream's frames to not update properly, or introduce weird bugs * removed unncessary changes
1 parent 5305b0c commit dabe2f4

2 files changed

Lines changed: 19 additions & 21 deletions

File tree

server.py

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ def create_ffmpeg_stream(
9595
if video_path is None:
9696
logging.info("video_path is None. ffmpeg_stream cancelled.")
9797
return 2
98+
99+
if (stop_all_videos()):
100+
101+
time.sleep(5)
102+
98103
# Create a subprocess to stream the video using FFmpeg
99104
command = [
100105
"ffmpeg",
@@ -132,13 +137,14 @@ def create_ffmpeg_stream(
132137
current_video_dict["title"] = title
133138
current_video_dict["thumbnail"] = thumbnail
134139

140+
logging.info(f"process {process.pid} started for {video_type.value} video: {video_path}")
135141
process_dict[video_type] = process.pid
136142
MetricsHandler.streams_count.labels(video_type=video_type.value).inc(amount=1)
137143
MetricsHandler.stream_state.labels(video_type=video_type.value).set(1)
138144
# the below function returns 0 if the video ended on its own
139145
# 137, 1
140146
exit_code = process.wait()
141-
logging.info(f"process {process.pid} started for {video_type.value} video: {video_path}")
147+
logging.info(f"process {process.pid} exited with code {exit_code}")
142148

143149
MetricsHandler.subprocess_count.labels(
144150
exit_code=exit_code,
@@ -151,22 +157,25 @@ def create_ffmpeg_stream(
151157
if (exit_code == 0 or video_type == State.PLAYING) and play_interlude_after and args.interlude:
152158
interlude_lock.release()
153159
hls_lock.release()
154-
logging.info(f"exiting create_ffmpeg_stream with exit code {exit_code}")
155160
return exit_code
156161

157162

158163
# stop the video by type
164+
# have stop_video_by_type return true if kill_child_processes was called
165+
# else have it return false
159166
def stop_video_by_type(video_type: State):
160167
if video_type in process_dict:
161168
kill_child_processes(process_dict[video_type])
162169
process_dict.pop(video_type)
170+
return True
171+
return False
163172

164-
173+
#stop_all_videos should also return a boolean, from what stop_video_by_type returned
165174
def stop_all_videos():
166-
stop_video_by_type(State.INTERLUDE)
167-
stop_video_by_type(State.PLAYING)
168-
175+
return stop_video_by_type(State.INTERLUDE) or stop_video_by_type(State.PLAYING)
176+
169177

178+
170179
# terminate a parent process and all its child processes using a specified signal.
171180
def kill_child_processes(parent_pid, sig=signal.SIGKILL):
172181
try:
@@ -205,7 +214,7 @@ def download_and_play_video(
205214
if video_path is None:
206215
video_cache.add(url)
207216
video_path = video_cache.find(Cache.get_video_id(url))
208-
stop_all_videos()
217+
209218
return create_ffmpeg_stream(
210219
video_path,
211220
State.PLAYING,
@@ -316,15 +325,15 @@ def run_hls_stream():
316325
stdin=subprocess.DEVNULL,
317326
stderr=subprocess.PIPE,
318327
)
319-
logging.info(f"HLS worker: started FFmpeg PID {proc.pid}")
328+
logging.info(f"HLS process started with pid {proc.pid}")
320329
# start the logging thread (non-blocking)
321330
threading.Thread(
322331
target=_monitor_ffmpeg, args=(proc,), daemon=True
323332
).start()
324333
# wait until a playback thread ends
325334
hls_lock.acquire()
326335
# rotate: kill, clean, loop
327-
logging.info("HLS worker: rotate signal, killing FFmpeg & cleaning dir")
336+
logging.info(f"hls_lock acquired, stopping pid {proc.pid}")
328337
kill_child_processes(proc.pid)
329338
_clean_hls_dir()
330339

@@ -354,13 +363,6 @@ async def state():
354363

355364
@app.post("/play/file")
356365
async def play_file(file_path: str = "cache", title: str = None, thumbnail: str = None):
357-
358-
# If any video playing, stop it
359-
for video_type in State:
360-
# Stop the video playing subprocess
361-
stop_video_by_type(video_type)
362-
363-
# Start thread to stream the video and provide a response
364366
try:
365367

366368
# check if we are going to play all videos or a single video in the cache

static/index.html

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ <h3 id="title"></h3>
7575
playButton.textContent = "Success!";
7676
playButton.disabled = true;
7777
document.getElementById("playing").style.display = "block";
78-
//Manually upate the urlInput and stop button, or else it won't update unless page is reloaded
79-
document.getElementById("urlInput").style.visibility = "hidden";
78+
//Manually upate the stop button, or else it won't update unless page is reloaded
8079
document.getElementById("playing").style.visibility="visible";
8180
setTimeout(() => {
8281
playButton.textContent = "Play";
@@ -91,14 +90,12 @@ <h3 id="title"></h3>
9190
async function Stop(e) {
9291
e.preventDefault();
9392
await fetch(stopURL.href, { method: "POST" });
94-
document.getElementById("urlInput").style.visibility = "visible";
9593
document.getElementById("metadata").style.visibility = "hidden";
9694
document.getElementById("playing").style.display = "none";
9795
}
9896
fetch(stateURL.href).then((response) => response.json()).then((json) => {
9997
const state = json["state"];
10098
if (state === "playing") {
101-
document.getElementById("urlInput").style.visibility = "hidden";
10299
document.getElementById("playing").style.visibility = "visible";
103100
document.getElementById('title').innerHTML = json["nowPlaying"]["title"];
104101
document.getElementById('thumbnail').src = json["nowPlaying"]["thumbnail"]
@@ -156,7 +153,6 @@ <h3 id="title"></h3>
156153
else {
157154
document.getElementById("metadata").style.visibility = "visible";
158155
document.getElementById("playing").style.display = "block";
159-
document.getElementById("urlInput").style.visibility = "hidden";
160156
document.getElementById('title').innerHTML = json["nowPlaying"]["title"];
161157
document.getElementById('thumbnail').src = json["nowPlaying"]["thumbnail"]
162158
}

0 commit comments

Comments
 (0)