diff --git a/CMakeLists.txt b/CMakeLists.txt index 2703d876..48432336 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.12) -project(lms VERSION 3.76.0) +project(lms VERSION 3.78.0) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake/modules/) diff --git a/Dockerfile-build-alpine b/Dockerfile-build-alpine index 14f06a52..f815419e 100644 --- a/Dockerfile-build-alpine +++ b/Dockerfile-build-alpine @@ -1,8 +1,9 @@ FROM --platform=$BUILDPLATFORM tonistiigi/xx AS xx -FROM --platform=$BUILDPLATFORM alpine:3.23 +FROM --platform=$BUILDPLATFORM alpine:3.24 ARG BUILD_PACKAGES="\ clang \ + llvm \ make \ cmake \ lld \ diff --git a/Dockerfile-release b/Dockerfile-release index ae2ef07e..f5fa9235 100644 --- a/Dockerfile-release +++ b/Dockerfile-release @@ -1,4 +1,4 @@ -FROM alpine:3.23 AS build +FROM alpine:3.24 AS build WORKDIR /tmp/workdir @@ -81,7 +81,7 @@ RUN \ make -j$(nproc) install # WT -ARG WT_VERSION=4.13.2 +ARG WT_VERSION=4.13.3 ARG WT_DEBUG=OFF RUN \ DIR=/tmp/wt && mkdir -p ${DIR} && cd ${DIR} && \ @@ -147,7 +147,7 @@ RUN \ rm -rf /tmp/fakeroot/share/Wt/resources/themes ## Release Stage -FROM alpine:3.23 AS release +FROM alpine:3.24 AS release LABEL maintainer="Emeric Poupon " ARG RUNTIME_PACKAGES=" \ diff --git a/README.md b/README.md index 8c1f3dfe..16e4499a 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ _LMS_ provides several ways to help you find the music you like: * ... __Note__: the recommendation engine supports two modes: -* **Tag-based**: uses metadata tags `genre` and `grouping`. +* **Tag-based**: uses metadata tags `genre`, `mood`, `grouping`, and `language`. * **Audio similarity**: uses MusicNN embeddings. Extraction throughput depends heavily on both the number of scanner threads and the speed of your storage. Typical reported speeds range from ~1k tracks/hour on a Raspberry Pi 4 (3 threads) to ~25k tracks/hour on an Intel Core i5-13500 (10 threads). To speed up extraction, consider tweaking `scanner-thread-count` in `lms.conf` (defaults to half the number of logical CPUs). ## About tags diff --git a/SUBSONIC.md b/SUBSONIC.md index 65f8b8ed..7fd8007f 100644 --- a/SUBSONIC.md +++ b/SUBSONIC.md @@ -75,6 +75,7 @@ The following extra fields are implemented: * [getPodcastEpisode](https://opensubsonic.netlify.app/docs/extensions/getpodcastepisode/) * [HTTP form POST](https://opensubsonic.netlify.app/docs/extensions/formpost/) * [Index based Queue](https://opensubsonic.netlify.app/docs/extensions/indexbasedqueue/) +* [Sonic similarity](https://opensubsonic.netlify.app/docs/extensions/sonicsimilarity/) * [Transcode offset](https://opensubsonic.netlify.app/docs/extensions/transcodeoffset/) * [Song Lyrics](https://opensubsonic.netlify.app/docs/extensions/songlyrics/) * [Transcoding](https://opensubsonic.netlify.app/docs/extensions/transcoding/) diff --git a/approot/admin-debugtools.xml b/approot/admin-debugtools.xml index 83025d9f..b7d380ea 100644 --- a/approot/admin-debugtools.xml +++ b/approot/admin-debugtools.xml @@ -8,8 +8,23 @@
${tr:Lms.Admin.DebugTools.Db.db} ${db} +
+ ${tr:Lms.Admin.DebugTools.PcmDecodingStats.pcm-decoding-stats} + ${pcm-decoding-stats} + +
+
+
+ ${run-btn class="btn btn-primary"} + ${download-btn class="btn btn-secondary ms-2"} + ${status} +
+
+
+
+ diff --git a/approot/main.xml b/approot/main.xml index 1fb31ea5..a3fb4c71 100644 --- a/approot/main.xml +++ b/approot/main.xml @@ -45,10 +45,8 @@
  • ${scanner class="dropdown-item"}
  • ${users class="dropdown-item"}
  • ${about class="dropdown-item"}
  • - ${}
  • ${debug-tools class="dropdown-item"}
  • - ${
    } ${} diff --git a/approot/messages.xml b/approot/messages.xml index 000dfef9..146bfdbe 100644 --- a/approot/messages.xml +++ b/approot/messages.xml @@ -129,7 +129,7 @@ Get report Last scan Not available -{1} files were scanned in {2} at {4} on {3} (UTC) - {5} errors, {6} duplicates +{1} files were scanned in {2} at {4} on {3} - {5} errors, {6} duplicates Missing artist name Unable to find track paths Unable to find the path "{1}" @@ -141,7 +141,7 @@ Scanner Status Not scheduled -Scheduled at {2} on {1} (UTC) +Scheduled at {2} on {1} Scanning: step {1}/{2} Associating artist images: {1}%... Associating external lyrics: {1}%... @@ -152,7 +152,7 @@ Checking for duplicate files... {1} files Checking for removed files... {1}% Compacting database... -Computing stats... {1}% +Computing stats... {1}% Extracting MusicNN embeddings: {1} of {2} files ({3}%) Optimizing database... {1}%... Reconciliating artists: {1} entries... @@ -169,6 +169,13 @@ Export query profiling data Database + +PCM decoding stats +Run bench +Download results +Running… +PCM decoding benchmark completed in {1} + Export traces Tracing @@ -221,7 +228,19 @@ Duration Filter added Filters + + Genre + Genres + + + Grouping + Groupings + Label + + Language + Languages + Lyricist Lyricists @@ -231,6 +250,10 @@ Mixer Mixers + + Mood + Moods + Most played MusicBrainz Artist MusicBrainz Release @@ -343,8 +366,24 @@ Audio These audio settings are local to your browser Internal +Last.fm +Last.fm API key +Last.fm API secret ListenBrainz ListenBrainz API token +Last.fm account +Linked +Link account +Unlink account +Link Last.fm account +Enter your Last.fm API key and shared secret (get them at last.fm/api/account/create), then click Authorize. +Authorize on Last.fm +Done, I've authorized +Didn't open? Click here to authorize on Last.fm +Unlink Last.fm account +Are you sure you want to unlink your Last.fm account? Scrobbling will stop until you link again. +Please enter your Last.fm API key and secret. +Last.fm authentication failed. Check your API key and secret. Change password Release Date (Ascending) Release Date (Descending) diff --git a/approot/messages_es.xml b/approot/messages_es.xml index bc9b0183..21ba6ad6 100644 --- a/approot/messages_es.xml +++ b/approot/messages_es.xml @@ -129,7 +129,7 @@ Informe Último escaneo No disponible -{1} ficheros analizados en {2} el {3} a las {4} (UTC) - {5} errores, {6} duplicados +{1} ficheros analizados en {2} el {3} a las {4} - {5} errores, {6} duplicados Falta el nombre del artista No se pudieron encontrar las rutas de las pistas No se pudo encontrar la ruta "{1}" @@ -141,7 +141,7 @@ Escanear Estado No progamado -Programado el {1} a las {2} (UTC) +Programado el {1} a las {2} Escaneando: etapa {1}/{2} Association des images des artistes: {1}%... Association des paroles externes: {1}%... @@ -152,7 +152,7 @@ Comprobando ficheros duplicados ... {1} ficheros Comprobando ficheros eliminados... {1}% Compactando la base de datos... -Calculando estadísticas... {1}% +Calculando estadísticas... {1}% Extracción de embeddings de MusicNN: {1} de {2} archivos ({3}%) Optimizando la base de datos... {1}%... Reconciliando artistas: {1} entradas... @@ -169,6 +169,13 @@ Exportar datos de perfil de consultas Base de datos + +Estadísticas de decodificación PCM +Ejecutar benchmark +Descargar resultados +Ejecutando… +Benchmark de decodificación PCM completado en {1} + Exportar las trazas Trazas @@ -221,7 +228,19 @@ Duración Filtro añadido Filtros + + Género + Géneros + + + Agrupación + Agrupaciones + Sello discográfico + + Idioma + Idiomas + Letrista Letristas @@ -231,6 +250,10 @@ Mezclador Mezcladores + + Estado de ánimo + Estados de ánimo + Reproducidos frecuentemente Artista de MusicBrainz Álbum de MusicBrainz @@ -345,6 +368,22 @@ Interno ListenBrainz Token de la API de ListenBrainz +Last.fm +Clave API de Last.fm +Secreto de API de Last.fm +Cuenta de Last.fm +Vinculado +Vincular cuenta +Desvincular cuenta +Vincular cuenta de Last.fm +Introduce tu clave API y secreto compartido de Last.fm (obténlos en last.fm/api/account/create), luego haz clic en Autorizar. +Autorizar en Last.fm +Hecho, he autorizado +¿No se abrió? Haz clic aquí para autorizar en Last.fm +Desvincular cuenta de Last.fm +¿Estás seguro de que deseas desvincular tu cuenta de Last.fm? El scrobbling se detendrá hasta que vuelvas a vincularla. +Por favor, introduce tu clave API y secreto de Last.fm. +Error de autenticación de Last.fm. Comprueba tu clave API y secreto. Cambiar contraseña Fecha de publicación (Ascendiente) Fecha de publicación (Descendiente) diff --git a/approot/messages_fr.xml b/approot/messages_fr.xml index 65d2a543..44a7f588 100644 --- a/approot/messages_fr.xml +++ b/approot/messages_fr.xml @@ -129,7 +129,7 @@ Rapport Dernier scan Non disponible -{1} fichiers analysés en {2} à {4} le {3} (UTC) - {5} erreurs, {6} duplicatas +{1} fichiers analysés en {2} à {4} le {3} - {5} erreurs, {6} duplicatas Nom de l'artiste manquant Impossible de trouver les chemins des pistes Impossible de trouver le chemin "{1}" @@ -141,7 +141,7 @@ Scanner Statut Non planifié -Planifié à {2} le {1} (UTC) +Planifié à {2} le {1} En cours de scan : étape {1}/{2} Association des images des artistes: {1}%... Association des paroles externes: {1}%... @@ -152,7 +152,7 @@ Vérification des fichiers dupliqués... {1} fichiers Vérification des fichiers supprimés... {1}% Compactage de la base de données... -Calcul des statistiques... {1}% +Calcul des statistiques... {1}% Extraction des embeddings MusicNN : {1} sur {2} fichiers ({3}%) Optimisation de la base de données... {1}%... Reconciliation des artistes: {1} entrées... @@ -169,6 +169,13 @@ Exporter les données de profilage des requêtes Base de données + +Statistiques de décodage PCM +Lancer le bench +Télécharger les résultats +En cours… +Benchmark de décodage PCM terminé en {1} + Exporter les traces Traces @@ -221,7 +228,19 @@ Durée Filtre ajouté Filtres + + Genre + Genres + + + Regroupement + Regroupements + Label + + Langue + Langues + Parolier Paroliers @@ -231,6 +250,10 @@ Mixeur Mixeurs + + Ambiance + Ambiances + Plus joués MusicBrainz Artist MusicBrainz Release @@ -345,6 +368,22 @@ Interne ListenBrainz Jeton d'API ListenBrainz +Last.fm +Clef API Last.fm +Secret API Last.fm +Compte Last.fm +Lié +Lier le compte +Délier le compte +Lier le compte Last.fm +Entrez votre clef API et votre secret partagé Last.fm (obtenez-les sur last.fm/api/account/create), puis cliquez sur Autoriser. +Autoriser sur Last.fm +Terminé, j'ai autorisé +Pas ouvert ? Cliquez ici pour autoriser sur Last.fm +Délier le compte Last.fm +Êtes-vous sûr de vouloir délier votre compte Last.fm ? Le scrobbling s'arrêtera jusqu'à ce que vous le reliiez. +Veuillez entrer votre clef API et votre secret Last.fm. +Échec de l'authentification Last.fm. Vérifiez votre clef API et votre secret. Changement de mot de passe Date de sortie (Croissant) Date de sortie (Décroissant) @@ -366,13 +405,13 @@ Mauvais mot de passe L'ancien mot de passe doit être renseigné Regénérer -Clé API copiée dans le presse-papiers ! +Clef API copiée dans le presse-papiers ! Supprimer -Supprimer la clé déconnectera tous les clients qui l'utilisent actuellement. -Supprimer la clé API ? +Supprimer la clef déconnectera tous les clients qui l'utilisent actuellement. +Supprimer la clef API ? Regénérer -Générer une nouvelle clé invalidera tous les clients utilisant actuellement la clé existante. -Regénérer la clé API ? +Générer une nouvelle clef invalidera tous les clients utilisant actuellement la clef existante. +Regénérer la clef API ? Mode ReplayGain Pas de ReplayGain Automatique @@ -390,7 +429,7 @@ Tous les artistes de piste API Subsonic Clef pour l'API OpenSubsonic -Utilisez cette clé d'API comme mot de passe pour les clients qui ne prennent pas en charge l'extension 'API Key Authentication' +Utilisez cette clef d'API comme mot de passe pour les clients qui ne prennent pas en charge l'extension 'API Key Authentication' Transcodage Appliquer le transcodage Toujours diff --git a/approot/messages_it.xml b/approot/messages_it.xml index 39051ccb..1ec58f23 100644 --- a/approot/messages_it.xml +++ b/approot/messages_it.xml @@ -129,7 +129,7 @@ Scarica un resoconto Ultima scansione Non disponibile -{1} file scansionati in {2} alle {3} il {4} (UTC) - {5} errori, {6} duplicati +{1} file scansionati in {2} alle {3} il {4} - {5} errori, {6} duplicati Nome dell'artista mancante Impossibile trovare i percorsi delle tracce Impossibile trovare il percorso "{1}" @@ -141,7 +141,7 @@ Scanner Stato Non pianificato -Programmato alle {2} del {1} (UTC) +Programmato alle {2} del {1} Scansione: passo {1}/{2} Associando immagini degli artisti: {1}%... Associazione dei testi esterni: {1}%... @@ -152,7 +152,7 @@ Controllo duplicati... {1} files Controllo file... {1}% Compattazione del database... -Calcolo statistiche... {1}% +Calcolo statistiche... {1}% Estrazione degli embeddings MusicNN: {1} di {2} file ({3}%) Ottimizzazione del database... {1}%... Riconciliazione artisti: {1} voci... @@ -169,6 +169,13 @@ Esporta i dati di profilazione delle query Database + +Statistiche di decodifica PCM +Avvia benchmark +Scarica risultati +In esecuzione… +Benchmark di decodifica PCM completato in {1} + Esporta tracce Tracing @@ -221,7 +228,19 @@ Durata Filtro aggiunto Filtri + + Genere + Generi + + + Raggruppamento + Raggruppamenti + Etichetta + + Lingua + Lingue + Paroliere Parolieri @@ -231,6 +250,10 @@ Tecnico del mixaggio Tecnici del mixaggio + + Umore + Umori + Più ascoltati Artista MusicBrainz Album MusicBrainz @@ -345,6 +368,22 @@ Interno ListenBrainz Token API ListenBrainz +Last.fm +Chiave API Last.fm +Segreto API Last.fm +Account Last.fm +Collegato +Collega account +Scollega account +Collega account Last.fm +Inserisci la chiave API e il segreto condiviso di Last.fm (ottenili su last.fm/api/account/create), poi clicca su Autorizza. +Autorizza su Last.fm +Fatto, ho autorizzato +Non si è aperto? Clicca qui per autorizzare su Last.fm +Scollega account Last.fm +Sei sicuro di voler scollegare il tuo account Last.fm? Lo scrobbling si interromperà finché non lo ricolleghi. +Inserisci la chiave API e il segreto Last.fm. +Autenticazione Last.fm fallita. Controlla la chiave API e il segreto. Cambia password Data di uscita (Crescente) Data di uscita (Decrescente) diff --git a/approot/messages_pl.xml b/approot/messages_pl.xml index 25eba67e..f35671cd 100644 --- a/approot/messages_pl.xml +++ b/approot/messages_pl.xml @@ -138,7 +138,7 @@ Pokaż raport Ostatnie skanowanie Niedostępne -Przeskanowano {1} plików w {2} o {4} dnia {3} (UTC) - {5} błędów, {6} duplikatów +Przeskanowano {1} plików w {2} o {4} dnia {3} - {5} błędów, {6} duplikatów Brakuje nazwy artysty Nie można znaleźć ścieżek utworów Nie można znaleźć ścieżki „{1}” @@ -150,7 +150,7 @@ Skaner Status Nie zaplanowano -Zaplanowano o {2} dnia {1} (UTC) +Zaplanowano o {2} dnia {1} Skanowanie: krok {1}/{2} Kojarzenie obrazów artystów: {1}%... Kojarzenie zewnętrznych tekstów: {1}%... @@ -165,7 +165,7 @@ Sprawdzanie plików... {1}% Prasowanie bazy danych... -Obliczanie statystyk... {1}% +Obliczanie statystyk... {1}% Ekstrakcja embeddingów MusicNN: {1} z {2} plików ({3}%) Optymalizowanie bazy danych... {1}%... Uzgodnianie artystów: {1} wpisów... @@ -186,6 +186,13 @@ Eksportuj dane profilowania zapytań Baza danych + +Statystyki dekodowania PCM +Uruchom benchmark +Pobierz wyniki +Trwa… +Test wydajności dekodowania PCM zakończony w {1} + Eksportuj ślady Śledzenie @@ -240,7 +247,22 @@ Długość Filtr dodany Filtry + + Gatunek + Gatunki + Gatunków + + + Grupowanie + Grupowania + Grupowań + Wytwórnia + + Język + Języki + Języków + Tekściarz Tekściarze @@ -252,6 +274,11 @@ Mikserzy Mikserów + + Nastrój + Nastroje + Nastrojów + Najczęściej odtwarzane Artysta w MusicBrainz Wydanie w MusicBrainz @@ -371,6 +398,22 @@ Wewnętrzny ListenBrainz ListenBrainz API token +Last.fm +Klucz API Last.fm +Sekret API Last.fm +Konto Last.fm +Połączono +Połącz konto +Odłącz konto +Połącz konto Last.fm +Wprowadź klucz API i współdzielony sekret Last.fm (uzyskaj je na last.fm/api/account/create), następnie kliknij Autoryzuj. +Autoryzuj na Last.fm +Gotowe, autoryzowałem +Nie otworzyło się? Kliknij tutaj, aby autoryzować na Last.fm +Odłącz konto Last.fm +Czy na pewno chcesz odłączyć swoje konto Last.fm? Scrobbling zostanie zatrzymany do czasu ponownego połączenia. +Wprowadź klucz API i sekret Last.fm. +Uwierzytelnianie Last.fm nie powiodło się. Sprawdź klucz API i sekret. Zmień hasło Data wydania (Rosnąco) Data wydania (Malejąco) diff --git a/approot/messages_zh.xml b/approot/messages_zh.xml index 8c4146d3..c0bc9f44 100644 --- a/approot/messages_zh.xml +++ b/approot/messages_zh.xml @@ -127,7 +127,7 @@ 生成报告 最后扫描 不可用 -已扫描 {1} 个文件,用时 {2},在 {3} 的 {4} (UTC) - {5} 个错误,{6} 个重复项 +已扫描 {1} 个文件,用时 {2},在 {3} 的 {4} - {5} 个错误,{6} 个重复项 缺少艺术家名称 无法找到曲目路径 无法找到路径 "{1}" @@ -139,7 +139,7 @@ 扫描器 状态 无计划 -计划于 {2} 在 {1} (UTC) +计划于 {2} 在 {1} 扫描中: 阶段 {1}/{2} 关联艺术家图片:{1}%... 关联外部歌词:{1}%... @@ -150,7 +150,7 @@ 检查重复文件... {1} 个文件 检查文件中... {1}% 正在压缩数据库... -正在计算统计信息... {1}% +正在计算统计信息... {1}% 正在提取 MusicNN 嵌入:{1} / {2} 个文件({3}%) 正在优化数据库... {1}%... 整理艺术家:{1} 条记录... @@ -167,6 +167,13 @@ 导出查询分析数据 数据库 + +PCM解码统计 +运行基准测试 +下载结果 +运行中… +PCM解码基准测试已在{1}内完成 + 导出跟踪 跟踪 @@ -213,10 +220,14 @@ 时长 过滤器已添加 过滤器 +流派 +分组 厂牌 +语言 作词者 音乐库 混音师 +情绪 播放最多 MusicBrainz 歌手 MusicBrainz 专辑 @@ -316,6 +327,22 @@ 内部 ListenBrainz ListenBrainz API 令牌 +Last.fm +Last.fm API 密钥 +Last.fm API 共享密钥 +Last.fm 账户 +已关联 +关联账户 +取消关联账户 +关联 Last.fm 账户 +输入您的 Last.fm API 密钥和共享密钥(从 last.fm/api/account/create 获取),然后点击授权。 +在 Last.fm 上授权 +完成,我已授权 +未打开?点击此处在 Last.fm 上授权 +取消关联 Last.fm 账户 +您确定要取消关联 Last.fm 账户吗?在重新关联之前,scrobbling 将停止。 +请输入您的 Last.fm API 密钥和共享密钥。 +Last.fm 认证失败。请检查您的 API 密钥和共享密钥。 更改密码 发行日期(升序) 发行日期(降序) diff --git a/approot/settings-services.xml b/approot/settings-services.xml index 62598371..9d31f847 100644 --- a/approot/settings-services.xml +++ b/approot/settings-services.xml @@ -39,4 +39,64 @@ ${save-btn class="btn btn-primary me-1"}${discard-btn class="btn btn-secondary"} + +
    +
    + ${tr:Lms.Settings.services.lastfm-card-title} + ${card-header-badge} +
    +
    + ${card-content} +
    +
    +
    + + + + + + + + + diff --git a/approot/tracks.xml b/approot/tracks.xml index d40598ab..76dba9ae 100644 --- a/approot/tracks.xml +++ b/approot/tracks.xml @@ -80,6 +80,46 @@