Skip to content

Commit

Permalink
fix: chunked stream failures on raspberry pi (#454)
Browse files Browse the repository at this point in the history
  • Loading branch information
vicwomg authored Dec 31, 2024
1 parent 7efa463 commit 2691376
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 24 deletions.
30 changes: 14 additions & 16 deletions pikaraoke/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -431,9 +431,11 @@ def logo():
return send_file(k.logo_path, mimetype="image/png")


@app.route("/end_song", methods=["GET"])
@app.route("/end_song", methods=["GET", "POST"])
def end_song():
k.end_song()
d = request.form.to_dict()
reason = d["reason"] if "reason" in d else None
k.end_song(reason)
return "ok"


Expand Down Expand Up @@ -708,24 +710,20 @@ def stream(id):
file_path = f"{get_tmp_dir()}/{id}.mp4"

def generate():
previous_size = -1
current_size = 0
position = 0 # Initialize the position variable
with open(file_path, "rb") as file: # Open the file outside the loop
while True:
current_size = os.path.getsize(file_path)
if current_size == previous_size:
# File size has stabilized, break the loop
break
chunk_size = 10240 * 1000 * 25 # Read file in up to 25MB chunks
with open(file_path, "rb") as file:
# Keep yielding file chunks as long as ffmpeg process is transcoding
while k.ffmpeg_process.poll() is None:
file.seek(position) # Move to the last read position
while True:
chunk = file.read(10240 * 100 * 30) # Read in 3mb chunks
if not chunk:
break # End of file reached
chunk = file.read(chunk_size)
if chunk is not None and len(chunk) > 0:
yield chunk
position += len(chunk) # Update the position with the size of the chunk
previous_size = current_size
time.sleep(1) # Wait a bit before checking the file size again
chunk = file.read(chunk_size) # Read the last chunk
yield chunk
position += len(chunk) # Update the position with the size of the chunk

return Response(generate(), mimetype="video/mp4")

Expand Down Expand Up @@ -794,7 +792,7 @@ def main():
default_screensaver_delay = 300
default_log_level = logging.INFO
default_prefer_hostname = False
default_buffer_size = 2500000
default_buffer_size = 150000

default_dl_dir = get_default_dl_dir(platform)
default_youtubedl_path = "yt-dlp"
Expand Down
16 changes: 14 additions & 2 deletions pikaraoke/karaoke.py
Original file line number Diff line number Diff line change
Expand Up @@ -469,7 +469,15 @@ def play_file(self, file_path, semitones=0):
if not requires_transcoding:
# simply copy file path to the tmp directory and the stream is ready
shutil.copy(file_path, fr.output_file)
is_transcoding_complete = True
max_retries = 5
while max_retries > 0:
if os.path.exists(fr.output_file):
is_transcoding_complete = True
break
max_retries -= 1
time.sleep(1)
if max_retries == 0:
logging.debug(f"Copying file failed: {fr.output_file}")
else:
self.kill_ffmpeg()
ffmpeg_cmd = build_ffmpeg_cmd(
Expand Down Expand Up @@ -560,8 +568,12 @@ def start_song(self):
logging.info(f"Song starting: {self.now_playing}")
self.is_playing = True

def end_song(self):
def end_song(self, reason=None):
logging.info(f"Song ending: {self.now_playing}")
if reason != None:
logging.info(f"Reason: {reason}")
if reason != "complete":
self.send_message_to_splash(f"Song ended abnormally: {reason}", "danger")
self.reset_now_playing()
self.kill_ffmpeg()
delete_tmp_dir()
Expand Down
14 changes: 8 additions & 6 deletions pikaraoke/templates/splash.html
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,9 @@
$("#video-container").hide();
}

function endSong() {
function endSong(reason=null) {
stopVideo();
$.get('{{ url_for("end_song") }}');
$.post('{{ url_for("end_song") }}', {reason: reason});
}

function executeCommand(callback) {
Expand Down Expand Up @@ -198,7 +198,7 @@
// handle timeout if video fails to play
setTimeout(() => {
if (!isVideoPlaying(video) && !video.paused) {
endSong();
endSong("failed to start");
}
}, 10000);
}
Expand Down Expand Up @@ -315,7 +315,7 @@
setTimeout(() => $.get('{{ url_for("start_song") }}'), 1200);
});
video.addEventListener("ended", () => {
endSong();
endSong("complete");
});
video.addEventListener("timeupdate", (e) => {
$("#current").text(formatTime(video.currentTime));
Expand All @@ -324,14 +324,16 @@
$("#video source")[0].addEventListener("error", (e) => {
console.log("Error while playing video.");
console.log(e);
endSong();
endSong("error while playing");
});

//make sure we end the song if the user closes the window or leaves page
window.addEventListener(
"beforeunload",
function (event) {
endSong();
if (isVideoPlaying(video)) {
endSong("splash screen closed");
}
},
true
);
Expand Down

0 comments on commit 2691376

Please sign in to comment.