Update la web app pour tirer partie du nouveau systeme de cache

This commit is contained in:
2025-10-28 00:10:51 +01:00
parent 8245fa6f41
commit 785f8d52a5
14 changed files with 459 additions and 43 deletions

View File

@@ -103,7 +103,16 @@ pub async fn add_with_metadata_extraction(
let flac_bytes = tokio::fs::read(&file_path).await?;
// Extraire les métadonnées
let metadata = crate::metadata::AudioMetadata::from_bytes(&flac_bytes)?;
let mut metadata = crate::metadata::AudioMetadata::from_bytes(&flac_bytes)?;
if let Some(transform) = cache.transform_metadata(&pk).await {
if let Some(mode) = transform.mode {
metadata.conversion = Some(crate::metadata::AudioConversionInfo {
mode,
source_codec: transform.input_codec,
});
}
}
let metadata_json: Value = serde_json::to_value(&metadata)
.map_err(|e| rusqlite::Error::ToSqlConversionFailure(Box::new(e)))?;
// Stocker dans la DB

View File

@@ -68,6 +68,23 @@ pub struct AudioMetadata {
/// Bitrate moyen (kbps)
#[cfg_attr(feature = "pmoserver", schema(example = 1411))]
pub bitrate: Option<u32>,
/// Informations sur la conversion appliquée lors de l'ingestion
#[cfg_attr(feature = "pmoserver", schema(example = json!({"mode":"transcode","source_codec":"mp3"})))]
pub conversion: Option<AudioConversionInfo>,
}
/// Informations sur le processus de conversion
#[derive(Debug, Clone, Serialize, Deserialize)]
#[cfg_attr(feature = "pmoserver", derive(ToSchema))]
pub struct AudioConversionInfo {
/// Mode de conversion (ex: "passthrough", "transcode")
#[cfg_attr(feature = "pmoserver", schema(example = "transcode"))]
pub mode: String,
/// Codec source détecté
#[cfg_attr(feature = "pmoserver", schema(example = "mp3"))]
pub source_codec: Option<String>,
}
impl AudioMetadata {
@@ -94,6 +111,7 @@ impl AudioMetadata {
sample_rate: properties.sample_rate(),
channels: properties.channels(),
bitrate: properties.audio_bitrate(),
conversion: None,
};
if let Some(tag) = tag {
@@ -232,6 +250,7 @@ impl Default for AudioMetadata {
sample_rate: None,
channels: None,
bitrate: None,
conversion: None,
}
}
}
@@ -256,6 +275,7 @@ mod tests {
sample_rate: Some(44100),
channels: Some(2),
bitrate: Some(1411),
conversion: None,
};
assert_eq!(
@@ -280,6 +300,7 @@ mod tests {
sample_rate: None,
channels: None,
bitrate: None,
conversion: None,
};
assert_eq!(metadata.collection_key(), None);

View File

@@ -6,13 +6,14 @@
//! while native FLAC input is forwarded byte-for-byte without re-encoding.
use bytes::Bytes;
use pmocache::download::TransformMetadata;
use pmocache::StreamTransformer;
use pmoflac::{transcode_to_flac_stream, AudioCodec, TranscodeOptions};
use tokio::io::{AsyncReadExt, AsyncWriteExt};
/// Creates the transformer consumed by the audio cache.
pub fn create_streaming_flac_transformer() -> StreamTransformer {
Box::new(|input, mut file, progress| {
Box::new(|input, mut file, context| {
Box::pin(async move {
let byte_stream = input.into_byte_stream();
let reader = StreamToAsyncRead::new(byte_stream);
@@ -21,7 +22,23 @@ pub fn create_streaming_flac_transformer() -> StreamTransformer {
.await
.map_err(|e| format!("Audio transcode error: {}", e))?;
log_stream_info(transcode.input_codec(), transcode.input_stream_info());
let codec = transcode.input_codec();
let info = transcode.input_stream_info().clone();
log_stream_info(codec, &info);
let mode = if transcode.is_passthrough() {
"passthrough"
} else {
"transcode"
};
context
.set_metadata(TransformMetadata {
mode: Some(mode.to_string()),
input_codec: Some(codec_to_string(codec)),
details: None,
})
.await;
let mut flac_stream = transcode.into_stream();
let mut buffer = vec![0u8; 64 * 1024];
@@ -42,7 +59,7 @@ pub fn create_streaming_flac_transformer() -> StreamTransformer {
.map_err(|e| format!("Failed to write FLAC file: {}", e))?;
total_written += read as u64;
progress(total_written);
context.report_progress(total_written);
}
file.flush()
@@ -70,6 +87,18 @@ fn log_stream_info(codec: AudioCodec, info: &pmoflac::StreamInfo) {
);
}
fn codec_to_string(codec: AudioCodec) -> String {
match codec {
AudioCodec::Flac => "flac",
AudioCodec::Mp3 => "mp3",
AudioCodec::OggVorbis => "ogg_vorbis",
AudioCodec::OggOpus => "ogg_opus",
AudioCodec::Wav => "wav",
AudioCodec::Aiff => "aiff",
}
.to_string()
}
/// Adapter exposing a byte stream as `AsyncRead`.
struct StreamToAsyncRead {
stream: futures_util::stream::BoxStream<'static, Result<Bytes, String>>,