mirror of
https://github.com/zoriya/Kyoo.git
synced 2025-06-01 12:44:45 -04:00
90 lines
2.7 KiB
Rust
90 lines
2.7 KiB
Rust
use crate::{error::ApiError, paths, state::Transcoder, transcode::TranscodeError};
|
|
use actix_files::NamedFile;
|
|
use actix_web::{get, web, Result};
|
|
|
|
/// Transcode audio
|
|
///
|
|
/// Get the selected audio
|
|
/// This route can take a few seconds to respond since it will way for at least one segment to be
|
|
/// available.
|
|
#[utoipa::path(
|
|
responses(
|
|
(status = 200, description = "Get the m3u8 playlist."),
|
|
(status = NOT_FOUND, description = "Invalid slug.")
|
|
),
|
|
params(
|
|
("resource" = String, Path, description = "Episode or movie"),
|
|
("slug" = String, Path, description = "The slug of the movie/episode."),
|
|
("audio" = u32, Path, description = "Specify the audio stream you want. For mappings, refer to the audios fields of the /watch response."),
|
|
)
|
|
)]
|
|
#[get("/{resource}/{slug}/audio/{audio}/index.m3u8")]
|
|
async fn get_audio_transcoded(
|
|
query: web::Path<(String, String, u32)>,
|
|
transcoder: web::Data<Transcoder>,
|
|
) -> Result<String, ApiError> {
|
|
let (resource, slug, audio) = query.into_inner();
|
|
let path = paths::get_path(resource, slug)
|
|
.await
|
|
.map_err(|_| ApiError::NotFound)?;
|
|
|
|
transcoder
|
|
.transcode_audio(path, audio)
|
|
.await
|
|
.map_err(|e| match e {
|
|
TranscodeError::ArgumentError(err) => ApiError::BadRequest { error: err },
|
|
TranscodeError::FFmpegError(err) => {
|
|
eprintln!(
|
|
"Unhandled ffmpeg error occured while transcoding audio: {}",
|
|
err
|
|
);
|
|
ApiError::InternalError
|
|
}
|
|
TranscodeError::ReadError(err) => {
|
|
eprintln!(
|
|
"Unhandled read error occured while transcoding audio: {}",
|
|
err
|
|
);
|
|
ApiError::InternalError
|
|
}
|
|
})
|
|
}
|
|
|
|
/// Get audio chunk
|
|
///
|
|
/// Retrieve a chunk of a transcoded audio.
|
|
#[utoipa::path(
|
|
responses(
|
|
(status = 200, description = "Get a hls chunk."),
|
|
(status = NOT_FOUND, description = "Invalid slug.")
|
|
),
|
|
params(
|
|
("resource" = String, Path, description = "Episode or movie"),
|
|
("slug" = String, Path, description = "The slug of the movie/episode."),
|
|
("audio" = u32, Path, description = "Specify the audio you want"),
|
|
("chunk" = u32, Path, description = "The number of the chunk"),
|
|
)
|
|
)]
|
|
#[get("/{resource}/{slug}/audio/{audio}/segments-{chunk}.ts")]
|
|
async fn get_audio_chunk(
|
|
query: web::Path<(String, String, u32, u32)>,
|
|
transcoder: web::Data<Transcoder>,
|
|
) -> Result<NamedFile, ApiError> {
|
|
let (resource, slug, audio, chunk) = query.into_inner();
|
|
let path = paths::get_path(resource, slug)
|
|
.await
|
|
.map_err(|_| ApiError::NotFound)?;
|
|
|
|
transcoder
|
|
.get_audio_segment(path, audio, chunk)
|
|
.await
|
|
.map_err(|_| ApiError::BadRequest {
|
|
error: "No transcode started for the selected show/audio.".to_string(),
|
|
})
|
|
.and_then(|path| {
|
|
NamedFile::open(path).map_err(|_| ApiError::BadRequest {
|
|
error: "Invalid segment number.".to_string(),
|
|
})
|
|
})
|
|
}
|