Fix FLAC pk collision by skipping header for pk calculation
Problem: All FLAC files with the same format (44.1kHz, stereo, 16-bit) had identical headers and thus the same pk (071c5713d5cf485ca688832207bef0f9). This caused the cache to think all tracks were the same file, regardless of channel selection or actual content. Solution: Skip the FLAC header (first 512 bytes) and calculate the pk from bytes 512-1024 (actual audio content) instead. This ensures each track gets a unique pk based on its actual audio data, not just its format header. Changes: - Modified add_from_reader_with_pk() to read 1024 bytes instead of 512 - Use bytes 512-1024 for pk calculation when explicit_pk is None - This works even with poor metadata (empty artist/title) - Maintains backward compatibility with explicit_pk parameter Fixes the issue where changing radio channel played the same song.
This commit is contained in:
@@ -135,6 +135,8 @@ impl NodeLogic for FlacCacheSinkLogic {
|
||||
// Ingérer le FLAC progressivement dans le cache
|
||||
// add_from_reader lance l'ingestion en arrière-plan et retourne dès que
|
||||
// le prebuffer (512 KB) est atteint, permettant un streaming progressif
|
||||
// Le cache skip automatiquement le header FLAC (512 octets) pour calculer le pk
|
||||
// à partir du contenu audio, évitant les collisions entre morceaux au même format
|
||||
let collection_ref = self.collection.as_deref();
|
||||
let cache_future = self.cache.add_from_reader(
|
||||
None,
|
||||
|
||||
@@ -368,13 +368,45 @@ impl<C: CacheConfig> Cache<C> {
|
||||
where
|
||||
R: AsyncRead + Send + Unpin + 'static,
|
||||
{
|
||||
// 1. Lire les 512 premiers octets pour calculer le pk
|
||||
let header = crate::download::peek_reader_header(&mut reader, 512)
|
||||
self.add_from_reader_with_pk(source_uri, reader, length, collection, None).await
|
||||
}
|
||||
|
||||
/// Ajoute un fichier à partir d'un flux avec un pk explicite optionnel.
|
||||
///
|
||||
/// Si `explicit_pk` est fourni, utilise ce pk au lieu de le calculer à partir du contenu.
|
||||
/// Ceci est utile quand plusieurs fichiers ont le même header mais doivent être cachés séparément
|
||||
/// (par exemple, des fichiers FLAC avec le même format mais du contenu différent).
|
||||
pub async fn add_from_reader_with_pk<R>(
|
||||
&self,
|
||||
source_uri: Option<&str>,
|
||||
mut reader: R,
|
||||
length: Option<u64>,
|
||||
collection: Option<&str>,
|
||||
explicit_pk: Option<String>,
|
||||
) -> Result<String>
|
||||
where
|
||||
R: AsyncRead + Send + Unpin + 'static,
|
||||
{
|
||||
// 1. Lire les premiers octets pour calculer le pk
|
||||
// Pour éviter les collisions entre fichiers FLAC au même format, on skip le header (512 octets)
|
||||
// et on utilise les octets 512-1024 (début du contenu audio) pour calculer le pk
|
||||
let buffer_size = if explicit_pk.is_none() { 1024 } else { 512 };
|
||||
let header = crate::download::peek_reader_header(&mut reader, buffer_size)
|
||||
.await
|
||||
.map_err(|e| anyhow!("Failed to peek reader header: {}", e))?;
|
||||
|
||||
// 2. Calculer le pk basé sur le contenu
|
||||
let pk = crate::cache_trait::pk_from_content_header(&header);
|
||||
// 2. Calculer le pk: si pas de pk explicite, utiliser octets 512-1024 au lieu de 0-512
|
||||
let pk = if let Some(explicit) = explicit_pk {
|
||||
explicit
|
||||
} else {
|
||||
// Skip les 512 premiers octets (header FLAC) et utiliser les 512 suivants
|
||||
let pk_bytes = if header.len() > 512 {
|
||||
&header[512..]
|
||||
} else {
|
||||
&header[..]
|
||||
};
|
||||
crate::cache_trait::pk_from_content_header(pk_bytes)
|
||||
};
|
||||
if let Some(uri) = source_uri {
|
||||
tracing::debug!("Computed pk {} for source_uri {}", pk, uri);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user