217 lines
7.7 KiB
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";
|
||
|
|
||
|
?>
|