It seemed more efficient to use range responses as supported by FileStream from axum-extra as I believe this should allow seeking backwards or forwards through the video with it raising an error (as it currently does when streaming the file in its entirety) but currently testing a ranged response seems to be slower to start with ffplay or vlc compared to a full download and crashes when trying to move backwards or forwards through the video.
Currently the route to handle the range response stream copying from some examples looks like:
Code: Select all
pub async fn stream(file_name: Query<FileName>, headers: HeaderMap) -> Response {
let range_header = headers
.get(header::RANGE)
.and_then(|value| value.to_str().ok());
let (start, end) = if let Some(range) = range_header {
if let Some(range) = parse_range_header(range) {
range
} else {
return (StatusCode::RANGE_NOT_SATISFIABLE, "Invalid Range").into_response();
}
} else {
(0, 0) // default range end = 0, if end = 0 end == file size - 1
};
let file_name = &file_name.filename;
let file_dir = var("VIDEO_SAVE_PATH").unwrap_or("/home".to_string());
let formated_path = format!("{file_dir}/{file_name}");
FileStream::<ReaderStream<File>>::try_range_response(formated_path, start, end)
.await
.map_err(|e| (StatusCode::NOT_FOUND, format!("File not found: {e}")))
.into_response()
}
fn parse_range_header(range: &str) -> Option<(u64, u64)> {
let range = range.strip_prefix("bytes=")?;
let mut parts = range.split('-');
let start = parts.next()?.parse::<u64>().ok()?;
let end = parts
.next()
.and_then(|s| s.parse::<u64>().ok())
.unwrap_or(0);
if start > end {
return None;
}
Some((start, end))
}
Code: Select all
VLC media player 3.0.16 Vetinari (revision 3.0.13-8-g41878ff4f2)
[0000563386aee580] main libvlc: Running vlc with the default interface. Use 'cvlc' to use vlc without interface.
Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome. Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.
[00007494280044d0] gl gl: Initialized libplacebo v4.192.1 (API v192)
libva info: VA-API version 1.14.0
libva error: vaGetDriverNameByIndex() failed with unknown libva error, driver_name = (null)
[00007494280044d0] glconv_vaapi_x11 gl error: vaInitialize: unknown libva error
libva info: VA-API version 1.14.0
libva info: Trying to open /usr/lib/x86_64-linux-gnu/dri/iHD_drv_video.so
libva info: Found init function __vaDriverInit_1_14
libva info: va_openDriver() returns 0
[0000749440111130] avcodec decoder: Using Intel iHD driver for Intel(R) Gen Graphics - 22.3.1 () for hardware decoding
[0000749440111130] main decoder error: Timestamp conversion failed for 2533334: no reference clock
[0000749440111130] main decoder error: Could not convert timestamp 0 for FFmpeg
[h264 @ 0x7494401d8a40] get_buffer() failed
[h264 @ 0x7494401d8a40] thread_get_buffer() failed
[h264 @ 0x7494401d8a40] decode_slice_header error
[h264 @ 0x7494401d8a40] no frame!