scripts-bash/local/bin/generate_playlist_fp.php

217 lines
7.7 KiB
PHP

<?php
// Fonction pour calculer le fingerprint d'un fichier audio
function calculate_fingerprint($file) {
$return_code = 0;
$file_bash = str_replace(['$'], ['\$'], $file);
exec("fpcalc -json \"$file_bash\" 2>&1", $output, $return_code);
// Vérifier s'il y a eu une erreur lors de l'exécution de la commande
if ($return_code !== 0) {
// Enregistrer l'erreur dans un fichier journal par exemple
error_log("Erreur lors du calcul du fingerprint pour le fichier \"$file_bash\" : " . implode("\n", $output));
return null; // Retourner null pour indiquer une erreur
}
// Traitement de la réponse
$result = json_decode(implode('', $output), true);
// Vérifier si le résultat est valide
if (isset($result['fingerprint'])) {
return $result['fingerprint']; // Retourner le fingerprint
} else {
// Enregistrer un message d'erreur dans le journal
error_log("Réponse invalide lors du calcul du fingerprint pour le fichier $file : " . implode("\n", $output));
return null; // Retourner null en cas de réponse invalide
}
}
function getTagValue($metadataInFile, $tagKey) {
// Vérifier si la clé existe dans le tableau et retourner sa valeur si c'est le cas
if (isset($metadataInFile['streams'][0]['tags'][$tagKey])) {
return $metadataInFile['streams'][0]['tags'][$tagKey];
} else {
// Retourner null si la clé n'existe pas
return null;
}
}
// Fonction pour extraire les métadonnées d'un fichier audio
function extract_metadata($file) {
# Extraire les métadonnées avec ffprobe
$ffprobe_output = shell_exec("ffprobe -hide_banner -loglevel fatal -show_error -show_format -show_streams -print_format json \"$file\"");
// Décoder la sortie JSON
$metadataInFile = json_decode($ffprobe_output, true);
// Vérifier si les métadonnées contiennent les tags
if (isset($metadataInFile['streams'][0]['tags'])) {
// Extraire les metadonnées
$metadata['ARTIST'] = getTagValue($metadataInFile, 'ARTIST');
$metadata['TITLE'] = getTagValue($metadataInFile, 'TITLE');
$metadata['ALBUM'] = getTagValue($metadataInFile, 'ALBUM');
$metadata['ACOUSTID'] = getTagValue($metadataInFile, 'ACOUSTID_ID');
$metadata['duration'] = isset($metadataInFile['format']['duration']) ? (float)$metadataInFile['format']['duration'] : null;
}
if (isset($metadata)) {
return $metadata;
} else {
return null;
}
}
// Vérifier si le nombre de paramètres est correct
if ($argc != 3) {
die("Usage: php scan_files.php <directory> <database>\n");
}
$directory = $argv[1];
$db_file = $argv[2];
// Vérifier si le dossier existe
if (!is_dir($directory)) {
die("Le dossier spécifié n'existe pas.\n");
}
// Vérifier si la base de données existe, sinon la créer
if (!file_exists($db_file)) {
echo "La base de données n'existe pas. Création en cours...\n";
$db = new PDO("sqlite:$db_file");
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// Créer les tables
$db->exec("CREATE TABLE IF NOT EXISTS files (
id INTEGER PRIMARY KEY,
file_path TEXT UNIQUE,
first_referenced DATETIME,
last_updated DATETIME
)");
$db->exec("CREATE TABLE IF NOT EXISTS fingerprints (
id INTEGER PRIMARY KEY,
file_id INTEGER UNIQUE,
fingerprint TEXT,
FOREIGN KEY (file_id) REFERENCES files(id)
)");
$db->exec("CREATE TABLE IF NOT EXISTS metadata (
file_id INTEGER PRIMARY KEY,
artist TEXT,
title TEXT,
album TEXT,
duration REAL,
acoustid TEXT,
FOREIGN KEY (file_id) REFERENCES files(id)
)");
// Création de la table system_info si elle n'existe pas déjà
$db->exec("CREATE TABLE IF NOT EXISTS system_info (
id INTEGER PRIMARY KEY,
version INTEGER NOT NULL
)");
// Insertion des données de version
$version = "1";
$insert_version_sql = "INSERT INTO system_info (version) VALUES (:version)";
$stmt = $db->prepare($insert_version_sql);
$stmt->bindParam(':version', $version, PDO::PARAM_STR);
$stmt->execute();
echo "Base de données créée avec succès.\n";
} else {
// Connexion à la base de données SQLite
$db = new PDO("sqlite:$db_file");
}
// Préparation de la requête d'insertion des fichiers
$insert_file_stmt = $db->prepare("INSERT INTO files (file_path, first_referenced, last_updated) VALUES (:file_path, DATETIME('now'), DATETIME('now'))");
// Préparer la requête SQL d'insertion ou de mise à jour des empreintes digitales
$insert_fingerprint_sql = "INSERT INTO fingerprints (file_id, fingerprint)
VALUES (:file_id, :fingerprint)
ON CONFLICT(file_id) DO UPDATE
SET fingerprint = :fingerprint";
$insert_fingerprint_stmt = $db->prepare($insert_fingerprint_sql);
// Préparer la requête SQL d'insertion ou de mise à jour des métadonnées
$insert_metadata_sql = "INSERT INTO metadata (file_id, artist, title, album, acoustid, duration)
VALUES (:file_id, :artist, :title, :album, :acoustid, :duration)
ON CONFLICT(file_id) DO UPDATE
SET artist = :artist,
title = :title,
album = :album,
acoustid = :acoustid,
duration = :duration";
$insert_metadata_stmt = $db->prepare($insert_metadata_sql);
$count = 0; // Initialisation du compteur
// Parcourir les fichiers audio
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($directory));
foreach ($iterator as $file) {
$file_bash = escapeshellarg($file);
if ($file->isFile() && in_array($file->getExtension(), ['mp3', 'opus', 'ogg', 'm4a'])) {
if ($count % 10 == 0) {
echo "\rProgress: $count files processed\n";
}
$file_path = $file->getPathname();
// Vérifier si le fichier existe déjà dans la base de données
$result = $db->query("SELECT id FROM files WHERE file_path = " . $db->quote($file_path));
$file_id = $result->fetchColumn();
if (!$file_id) {
// Insérer le fichier dans la base de données
$insert_file_stmt->execute([':file_path' => $file_path]);
$file_id = $db->lastInsertId();
// Calculer le fingerprint du fichier
// $fingerprint = calculate_fingerprint($file_path);
// Insérer le fingerprint dans la base de données
// $insert_fingerprint_stmt->execute([':file_id' => $file_id, ':fingerprint' => $fingerprint]);
} else {
// Mettre à jour la date de dernière mise à jour du fichier
$db->exec("UPDATE files SET last_updated = DATETIME('now') WHERE id = $file_id");
}
// Extraire les métadonnées du fichier audio
$metadata = extract_metadata($file_path);
// Insérer les métadonnées dans la base de données
$insert_metadata_stmt->execute([
':file_id' => $file_id,
':artist' => isset($metadata['ARTIST']) ? $metadata['ARTIST'] : null,
':title' => isset($metadata['TITLE']) ? $metadata['TITLE'] : null,
':album' => isset($metadata['ALBUM']) ? $metadata['ALBUM'] : null,
':acoustid' => isset($metadata['ACOUSTID']) ? $metadata['ACOUSTID'] : null,
':duration' => isset($metadata['duration']) ? (int)$metadata['duration'] : null
]);
$count++;
}
}
// Fermer la connexion à la base de données
$db = null;
echo "Terminé.\n";
?>