Merge remote-tracking branch 'jellyfinorigin/master' into feature/EFUserData

This commit is contained in:
JPVenson
2024-10-08 09:34:34 +00:00
185 changed files with 9576 additions and 3501 deletions

View File

@@ -20,7 +20,9 @@ namespace Emby.Server.Implementations
{ PlaylistsAllowDuplicatesKey, bool.FalseString },
{ BindToUnixSocketKey, bool.FalseString },
{ SqliteCacheSizeKey, "20000" },
{ FfmpegSkipValidationKey, bool.FalseString }
{ FfmpegSkipValidationKey, bool.FalseString },
{ FfmpegImgExtractPerfTradeoffKey, bool.FalseString },
{ DetectNetworkChangeKey, bool.TrueString }
};
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -314,6 +314,12 @@ namespace Emby.Server.Implementations.IO
var ex = e.GetException();
var dw = (FileSystemWatcher)sender;
if (ex is UnauthorizedAccessException unauthorizedAccessException)
{
_logger.LogError(unauthorizedAccessException, "Permission error for Directory watcher: {Path}", dw.Path);
return;
}
_logger.LogError(ex, "Error in Directory watcher for: {Path}", dw.Path);
DisposeWatcher(dw, true);

View File

@@ -149,6 +149,26 @@ namespace Emby.Server.Implementations.IO
}
}
/// <inheritdoc />
public void MoveDirectory(string source, string destination)
{
try
{
Directory.Move(source, destination);
}
catch (IOException)
{
// Cross device move requires a copy
Directory.CreateDirectory(destination);
foreach (string file in Directory.GetFiles(source))
{
File.Copy(file, Path.Combine(destination, Path.GetFileName(file)), true);
}
Directory.Delete(source, true);
}
}
/// <summary>
/// Returns a <see cref="FileSystemMetadata"/> object for the specified file or directory path.
/// </summary>
@@ -327,11 +347,7 @@ namespace Emby.Server.Implementations.IO
}
}
/// <summary>
/// Gets the creation time UTC.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>DateTime.</returns>
/// <inheritdoc />
public virtual DateTime GetCreationTimeUtc(string path)
{
return GetCreationTimeUtc(GetFileSystemInfo(path));
@@ -368,11 +384,7 @@ namespace Emby.Server.Implementations.IO
}
}
/// <summary>
/// Gets the last write time UTC.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>DateTime.</returns>
/// <inheritdoc />
public virtual DateTime GetLastWriteTimeUtc(string path)
{
return GetLastWriteTimeUtc(GetFileSystemInfo(path));
@@ -446,11 +458,7 @@ namespace Emby.Server.Implementations.IO
File.SetAttributes(path, attributes);
}
/// <summary>
/// Swaps the files.
/// </summary>
/// <param name="file1">The file1.</param>
/// <param name="file2">The file2.</param>
/// <inheritdoc />
public virtual void SwapFiles(string file1, string file2)
{
ArgumentException.ThrowIfNullOrEmpty(file1);

View File

@@ -50,6 +50,10 @@ namespace Emby.Server.Implementations.Library
"**/lost+found/**",
"**/lost+found",
// Trickplay files
"**/*.trickplay",
"**/*.trickplay/**",
// WMC temp recording directories that will constantly be written to
"**/TempRec/**",
"**/TempRec",

View File

@@ -2725,33 +2725,9 @@ namespace Emby.Server.Implementations.Library
public string GetPathAfterNetworkSubstitution(string path, BaseItem? ownerItem)
{
string? newPath;
if (ownerItem is not null)
{
var libraryOptions = GetLibraryOptions(ownerItem);
if (libraryOptions is not null)
{
foreach (var pathInfo in libraryOptions.PathInfos)
{
if (path.TryReplaceSubPath(pathInfo.Path, pathInfo.NetworkPath, out newPath))
{
return newPath;
}
}
}
}
var metadataPath = _configurationManager.Configuration.MetadataPath;
var metadataNetworkPath = _configurationManager.Configuration.MetadataNetworkPath;
if (path.TryReplaceSubPath(metadataPath, metadataNetworkPath, out newPath))
{
return newPath;
}
foreach (var map in _configurationManager.Configuration.PathSubstitutions)
{
if (path.TryReplaceSubPath(map.From, map.To, out newPath))
if (path.TryReplaceSubPath(map.From, map.To, out var newPath))
{
return newPath;
}
@@ -3070,15 +3046,6 @@ namespace Emby.Server.Implementations.Library
SyncLibraryOptionsToLocations(virtualFolderPath, libraryOptions);
foreach (var originalPathInfo in libraryOptions.PathInfos)
{
if (string.Equals(mediaPath.Path, originalPathInfo.Path, StringComparison.Ordinal))
{
originalPathInfo.NetworkPath = mediaPath.NetworkPath;
break;
}
}
CollectionFolder.SaveLibraryOptions(virtualFolderPath, libraryOptions);
}

View File

@@ -129,5 +129,11 @@
"TaskCleanCollectionsAndPlaylists": "Ачысціце калекцыі і спісы прайгравання",
"TaskCleanCollectionsAndPlaylistsDescription": "Выдаляе элементы з калекцый і спісаў прайгравання, якія больш не існуюць.",
"TaskAudioNormalizationDescription": "Сканіруе файлы на прадмет нармалізацыі гуку.",
"TaskAudioNormalization": "Нармалізацыя гуку"
"TaskAudioNormalization": "Нармалізацыя гуку",
"TaskExtractMediaSegmentsDescription": "Выдае або атрымлівае медыясегменты з убудоў з падтрымкай MediaSegment.",
"TaskMoveTrickplayImagesDescription": "Перамяшчае існуючыя файлы trickplay у адпаведнасці з наладамі бібліятэкі.",
"TaskDownloadMissingLyrics": "Спампаваць зніклыя тэксты песень",
"TaskDownloadMissingLyricsDescription": "Спампоўвае тэксты для песень",
"TaskExtractMediaSegments": "Сканіраванне медыя-сегмента",
"TaskMoveTrickplayImages": "Перанесці месцазнаходжанне выявы Trickplay"
}

View File

@@ -130,5 +130,7 @@
"TaskCleanCollectionsAndPlaylistsDescription": "Esborra elements de col·leccions i llistes de reproducció que ja no existeixen.",
"TaskCleanCollectionsAndPlaylists": "Neteja col·leccions i llistes de reproducció",
"TaskAudioNormalization": "Normalització d'Àudio",
"TaskAudioNormalizationDescription": "Escaneja arxius per dades de normalització d'àudio."
"TaskAudioNormalizationDescription": "Escaneja arxius per dades de normalització d'àudio.",
"TaskDownloadMissingLyricsDescription": "Baixar lletres de les cançons",
"TaskDownloadMissingLyrics": "Baixar lletres que falten"
}

View File

@@ -132,5 +132,9 @@
"TaskAudioNormalization": "Normalizace zvuku",
"TaskAudioNormalizationDescription": "Skenovat soubory za účelem normalizace zvuku.",
"TaskDownloadMissingLyrics": "Stáhnout chybějící texty k písni",
"TaskDownloadMissingLyricsDescription": "Stáhne texty k písni"
"TaskDownloadMissingLyricsDescription": "Stáhne texty k písni",
"TaskExtractMediaSegments": "Skenování segmentů médií",
"TaskExtractMediaSegmentsDescription": "Extrahuje či získá segmenty médií pomocí zásuvných modulů MediaSegment.",
"TaskMoveTrickplayImages": "Přesunout úložiště obrázků Trickplay",
"TaskMoveTrickplayImagesDescription": "Přesune existující soubory Trickplay podle nastavení knihovny."
}

View File

@@ -132,5 +132,9 @@
"TaskAudioNormalization": "Audio Normalisierung",
"TaskAudioNormalizationDescription": "Durchsucht Dateien nach Audionormalisierungsdaten.",
"TaskDownloadMissingLyricsDescription": "Lädt Songtexte herunter",
"TaskDownloadMissingLyrics": "Fehlende Songtexte herunterladen"
"TaskDownloadMissingLyrics": "Fehlende Songtexte herunterladen",
"TaskExtractMediaSegments": "Scanne Mediensegmente",
"TaskExtractMediaSegmentsDescription": "Extrahiert oder empfängt Mediensegmente von Plugins die Mediensegmente nutzen.",
"TaskMoveTrickplayImages": "Verzeichnis für Trickplay-Bilder migrieren",
"TaskMoveTrickplayImagesDescription": "Trickplay-Bilder werden entsprechend der Bibliothekseinstellungen verschoben."
}

View File

@@ -132,5 +132,9 @@
"TaskAudioNormalization": "Audio Normalisation",
"TaskAudioNormalizationDescription": "Scans files for audio normalisation data.",
"TaskDownloadMissingLyrics": "Download missing lyrics",
"TaskDownloadMissingLyricsDescription": "Downloads lyrics for songs"
"TaskDownloadMissingLyricsDescription": "Downloads lyrics for songs",
"TaskExtractMediaSegments": "Media Segment Scan",
"TaskExtractMediaSegmentsDescription": "Extracts or obtains media segments from MediaSegment enabled plugins.",
"TaskMoveTrickplayImages": "Migrate Trickplay Image Location",
"TaskMoveTrickplayImagesDescription": "Moves existing trickplay files according to the library settings."
}

View File

@@ -131,5 +131,9 @@
"TaskKeyframeExtractor": "Keyframe Extractor",
"TaskKeyframeExtractorDescription": "Extracts keyframes from video files to create more precise HLS playlists. This task may run for a long time.",
"TaskCleanCollectionsAndPlaylists": "Clean up collections and playlists",
"TaskCleanCollectionsAndPlaylistsDescription": "Removes items from collections and playlists that no longer exist."
"TaskCleanCollectionsAndPlaylistsDescription": "Removes items from collections and playlists that no longer exist.",
"TaskExtractMediaSegments": "Media Segment Scan",
"TaskExtractMediaSegmentsDescription": "Extracts or obtains media segments from MediaSegment enabled plugins.",
"TaskMoveTrickplayImages": "Migrate Trickplay Image Location",
"TaskMoveTrickplayImagesDescription": "Moves existing trickplay files according to the library settings."
}

View File

@@ -132,5 +132,9 @@
"TaskCleanCollectionsAndPlaylists": "Limpiar colecciones y listas de reproducción",
"TaskCleanCollectionsAndPlaylistsDescription": "Elimina elementos de colecciones y listas de reproducción que ya no existen.",
"TaskDownloadMissingLyrics": "Descargar letra faltante",
"TaskDownloadMissingLyricsDescription": "Descarga letras de canciones"
"TaskDownloadMissingLyricsDescription": "Descarga letras de canciones",
"TaskExtractMediaSegments": "Escanear Segmentos de Media",
"TaskExtractMediaSegmentsDescription": "Extrae u obtiene segmentos de medio de plugins habilitados para MediaSegment.",
"TaskMoveTrickplayImagesDescription": "Mueve archivos existentes de trickplay de acuerdo a la configuración de la biblioteca.",
"TaskMoveTrickplayImages": "Migrar Ubicación de Imagen de Trickplay"
}

View File

@@ -102,7 +102,7 @@
"Forced": "Sunnitud",
"Folders": "Kaustad",
"Favorites": "Lemmikud",
"FailedLoginAttemptWithUserName": "{0} - sisselogimine nurjus",
"FailedLoginAttemptWithUserName": "Sisselogimine nurjus aadressilt {0}",
"DeviceOnlineWithName": "{0} on ühendatud",
"DeviceOfflineWithName": "{0} katkestas ühenduse",
"Default": "Vaikimisi",
@@ -129,5 +129,11 @@
"TaskAudioNormalization": "Heli Normaliseerimine",
"TaskAudioNormalizationDescription": "Skaneerib faile heli normaliseerimise andmete jaoks.",
"TaskCleanCollectionsAndPlaylistsDescription": "Eemaldab kogumikest ja esitusloenditest asjad, mida enam ei eksisteeri.",
"TaskCleanCollectionsAndPlaylists": "Puhasta kogumikud ja esitusloendid"
"TaskCleanCollectionsAndPlaylists": "Puhasta kogumikud ja esitusloendid",
"TaskDownloadMissingLyrics": "Lae alla puuduolev lüürika",
"TaskDownloadMissingLyricsDescription": "Lae lauludele alla lüürika",
"TaskMoveTrickplayImagesDescription": "Liigutab trickplay pildid meediakogu sätete kohaselt.",
"TaskExtractMediaSegments": "Meediasegmentide skaneerimine",
"TaskExtractMediaSegmentsDescription": "Eraldab või võtab meediasegmendid MediaSegment'i lubavatest pluginatest.",
"TaskMoveTrickplayImages": "Migreeri trickplay piltide asukoht"
}

View File

@@ -132,5 +132,9 @@
"TaskAudioNormalizationDescription": "بررسی فایل برای داده‌های نرمال کردن صدا.",
"TaskDownloadMissingLyrics": "دانلود متن‌های ناموجود",
"TaskDownloadMissingLyricsDescription": "دانلود متن شعر‌ها",
"TaskAudioNormalization": "نرمال کردن صدا"
"TaskAudioNormalization": "نرمال کردن صدا",
"TaskExtractMediaSegments": "بررسی بخش محتوا",
"TaskExtractMediaSegmentsDescription": "بخش‌های محتوا را از افزونه‌های مربوط استخراح می‌کند.",
"TaskMoveTrickplayImages": "جابه‌جایی عکس‌های Trickplay",
"TaskMoveTrickplayImagesDescription": "داده‌های Trickplay را با توجه به تنظیمات کتاب‌خانه جابه‌جا می‌کند."
}

View File

@@ -129,5 +129,6 @@
"TaskCleanCollectionsAndPlaylistsDescription": "Poistaa kohteet kokoelmista ja soittolistoista joita ei ole enää olemassa.",
"TaskCleanCollectionsAndPlaylists": "Puhdista kokoelmat ja soittolistat",
"TaskAudioNormalization": "Äänenvoimakkuuden normalisointi",
"TaskAudioNormalizationDescription": "Etsii tiedostoista äänenvoimakkuuden normalisointitietoja."
"TaskAudioNormalizationDescription": "Etsii tiedostoista äänenvoimakkuuden normalisointitietoja.",
"TaskDownloadMissingLyrics": "Lataa puuttuva lyriikka"
}

View File

@@ -132,5 +132,9 @@
"TaskAudioNormalization": "Normalisation audio",
"TaskAudioNormalizationDescription": "Analyse les fichiers à la recherche de données de normalisation audio.",
"TaskDownloadMissingLyricsDescription": "Téléchargement des paroles des chansons",
"TaskDownloadMissingLyrics": "Télécharger les paroles des chansons manquantes"
"TaskDownloadMissingLyrics": "Télécharger les paroles des chansons manquantes",
"TaskExtractMediaSegments": "Analyse des segments de média",
"TaskMoveTrickplayImages": "Changer l'emplacement des images Trickplay",
"TaskExtractMediaSegmentsDescription": "Extrait ou obtient des segments de média à partir des plugins compatibles avec MediaSegment.",
"TaskMoveTrickplayImagesDescription": "Déplace les fichiers trickplay existants en fonction des paramètres de la bibliothèque."
}

View File

@@ -1,7 +1,7 @@
{
"Albums": "Álbumes",
"Collections": "Colecións",
"ChapterNameValue": "Capítulos {0}",
"Collections": "Coleccións",
"ChapterNameValue": "Capítulo {0}",
"Channels": "Canles",
"CameraImageUploadedFrom": "Cargouse unha nova imaxe da cámara desde {0}",
"Books": "Libros",

View File

@@ -60,7 +60,7 @@
"NotificationOptionUserLockedOut": "משתמש ננעל",
"NotificationOptionVideoPlayback": "ניגון וידאו החל",
"NotificationOptionVideoPlaybackStopped": "ניגון וידאו הופסק",
"Photos": "תמונות",
"Photos": "צילומים",
"Playlists": "רשימות נגינה",
"Plugin": "תוסף",
"PluginInstalledWithName": "{0} הותקן",
@@ -130,5 +130,11 @@
"TaskAudioNormalization": "נרמול שמע",
"TaskCleanCollectionsAndPlaylistsDescription": "מנקה פריטים לא קיימים מאוספים ורשימות השמעה.",
"TaskAudioNormalizationDescription": "מחפש קבצי נורמליזציה של שמע.",
"TaskCleanCollectionsAndPlaylists": "מנקה אוספים ורשימות השמעה"
"TaskCleanCollectionsAndPlaylists": "מנקה אוספים ורשימות השמעה",
"TaskDownloadMissingLyrics": "הורדת מילים חסרות",
"TaskDownloadMissingLyricsDescription": "הורדת מילים לשירים",
"TaskMoveTrickplayImages": "מעביר את מיקום תמונות Trickplay",
"TaskExtractMediaSegments": "סריקת מדיה",
"TaskExtractMediaSegmentsDescription": "מחלץ חלקי מדיה מתוספים המאפשרים זאת.",
"TaskMoveTrickplayImagesDescription": "מזיז קבצי trickplay קיימים בהתאם להגדרות הספרייה."
}

View File

@@ -1,13 +1,13 @@
{
"Albums": "Albumok",
"AppDeviceValues": "Program: {0}, Eszköz: {1}",
"AppDeviceValues": "Program: {0}, eszköz: {1}",
"Application": "Alkalmazás",
"Artists": "Előadók",
"AuthenticationSucceededWithUserName": "{0} sikeresen hitelesítve",
"Books": "Könyvek",
"CameraImageUploadedFrom": "Új kamerakép lett feltöltve innen: {0}",
"Channels": "Csatornák",
"ChapterNameValue": "Jelenet {0}",
"ChapterNameValue": "{0}. jelenet",
"Collections": "Gyűjtemények",
"DeviceOfflineWithName": "{0} kijelentkezett",
"DeviceOnlineWithName": "{0} belépett",
@@ -15,31 +15,31 @@
"Favorites": "Kedvencek",
"Folders": "Könyvtárak",
"Genres": "Műfajok",
"HeaderAlbumArtists": "Album előadók",
"HeaderAlbumArtists": "Albumelőadók",
"HeaderContinueWatching": "Megtekintés folytatása",
"HeaderFavoriteAlbums": "Kedvenc Albumok",
"HeaderFavoriteArtists": "Kedvenc Előadók",
"HeaderFavoriteEpisodes": "Kedvenc Epizódok",
"HeaderFavoriteShows": "Kedvenc Sorozatok",
"HeaderFavoriteSongs": "Kedvenc Dalok",
"HeaderFavoriteAlbums": "Kedvenc albumok",
"HeaderFavoriteArtists": "Kedvenc előadók",
"HeaderFavoriteEpisodes": "Kedvenc epizódok",
"HeaderFavoriteShows": "Kedvenc sorozatok",
"HeaderFavoriteSongs": "Kedvenc számok",
"HeaderLiveTV": "Élő TV",
"HeaderNextUp": "Következik",
"HeaderRecordingGroups": "Felvevő Csoportok",
"HomeVideos": "Otthoni Videók",
"Inherit": "Örökölt",
"ItemAddedWithName": "{0} hozzáadva a könyvtárhoz",
"ItemRemovedWithName": "{0} eltávolítva a könyvtárból",
"HeaderRecordingGroups": "Felvételi csoportok",
"HomeVideos": "Otthoni videók",
"Inherit": "Öröklés",
"ItemAddedWithName": "{0} hozzáadva a médiatárhoz",
"ItemRemovedWithName": "{0} eltávolítva a médiatárból",
"LabelIpAddressValue": "IP-cím: {0}",
"LabelRunningTimeValue": "Lejátszási idő: {0}",
"Latest": "Legújabb",
"MessageApplicationUpdated": "A Jellyfin kiszolgáló frissítve lett",
"MessageApplicationUpdatedTo": "A Jellyfin kiszolgáló frissítve lett a következőre: {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "A kiszolgálókonfigurációs rész frissítve lett: {0}",
"MessageServerConfigurationUpdated": "Kiszolgálókonfiguráció frissítve lett",
"MessageServerConfigurationUpdated": "A kiszolgálókonfiguráció frissítve lett",
"MixedContent": "Vegyes tartalom",
"Movies": "Filmek",
"Music": "Zenék",
"MusicVideos": "Zenei videóklippek",
"MusicVideos": "Zenei videóklipek",
"NameInstallFailed": "{0} sikertelen telepítés",
"NameSeasonNumber": "{0}. évad",
"NameSeasonUnknown": "Ismeretlen évad",
@@ -56,7 +56,7 @@
"NotificationOptionPluginUninstalled": "Bővítmény eltávolítva",
"NotificationOptionPluginUpdateInstalled": "Bővítményfrissítés telepítve",
"NotificationOptionServerRestartRequired": "A kiszolgáló újraindítása szükséges",
"NotificationOptionTaskFailed": "Ütemezett feladat hiba",
"NotificationOptionTaskFailed": "Hiba az ütemezett feladatban",
"NotificationOptionUserLockedOut": "Felhasználó tiltva",
"NotificationOptionVideoPlayback": "Videólejátszás elkezdve",
"NotificationOptionVideoPlaybackStopped": "Videólejátszás leállítva",
@@ -107,7 +107,7 @@
"TaskCleanCache": "Gyorsítótár könyvtárának ürítése",
"TasksChannelsCategory": "Internetes csatornák",
"TasksApplicationCategory": "Alkalmazás",
"TasksLibraryCategory": "Könyvtár",
"TasksLibraryCategory": "Médiatár",
"TasksMaintenanceCategory": "Karbantartás",
"TaskDownloadMissingSubtitlesDescription": "A metaadat-konfiguráció alapján ellenőrzi és letölti a hiányzó feliratokat az internetről.",
"TaskDownloadMissingSubtitles": "Hiányzó feliratok letöltése",
@@ -119,16 +119,22 @@
"Undefined": "Meghatározatlan",
"Forced": "Kényszerített",
"Default": "Alapértelmezett",
"TaskOptimizeDatabaseDescription": "Tömöríti az adatbázist és csonkolja a szabad helyet. A feladat futtatása a könyvtár beolvasása után, vagy egyéb, adatbázis-módosítást igénylő változtatások végrehajtása javíthatja a teljesítményt.",
"TaskOptimizeDatabaseDescription": "Tömöríti az adatbázist és csonkolja a szabad helyet. A feladat futtatása a médiatár beolvasása, vagy egyéb adatbázis-módosítást igénylő változtatás végrehajtása után, javíthatja a teljesítményt.",
"TaskOptimizeDatabase": "Adatbázis optimalizálása",
"TaskKeyframeExtractor": "Kulcsképkockák kibontása",
"TaskKeyframeExtractorDescription": "Kibontja a kulcsképkockákat a videófájlokból, hogy pontosabb HLS lejátszási listákat hozzon létre. Ez a feladat hosszú ideig tarthat.",
"External": "Külső",
"HearingImpaired": "Hallássérült",
"TaskRefreshTrickplayImages": "Trickplay képek generálása",
"TaskRefreshTrickplayImages": "Trickplay képek előállítása",
"TaskRefreshTrickplayImagesDescription": "Trickplay előnézetet készít az engedélyezett könyvtárakban lévő videókhoz.",
"TaskAudioNormalization": "Hangerő Normalizáció",
"TaskAudioNormalization": "Hangerő-normalizálás",
"TaskCleanCollectionsAndPlaylistsDescription": "Nem létező elemek törlése a gyűjteményekből és lejátszási listákról.",
"TaskAudioNormalizationDescription": "Hangerő normalizációs adatok keresése.",
"TaskCleanCollectionsAndPlaylists": "Gyűjtemények és lejátszási listák optimalizálása"
"TaskAudioNormalizationDescription": "Hangerő-normalizálási adatok keresése.",
"TaskCleanCollectionsAndPlaylists": "Gyűjtemények és lejátszási listák optimalizálása",
"TaskExtractMediaSegments": "Médiaszegmens felismerése",
"TaskDownloadMissingLyrics": "Hiányzó szöveg letöltése",
"TaskDownloadMissingLyricsDescription": "Zenék szövegének letöltése",
"TaskMoveTrickplayImages": "Trickplay képek helyének átköltöztetése",
"TaskMoveTrickplayImagesDescription": "A médiatár-beállításoknak megfelelően áthelyezi a meglévő trickplay fájlokat.",
"TaskExtractMediaSegmentsDescription": "Kinyeri vagy megszerzi a médiaszegmenseket a MediaSegment támogatással rendelkező bővítményekből."
}

View File

@@ -132,5 +132,7 @@
"TaskAudioNormalization": "Normalizzazione dell'audio",
"TaskAudioNormalizationDescription": "Scansiona i file alla ricerca dei dati per la normalizzazione dell'audio.",
"TaskDownloadMissingLyricsDescription": "Scarica testi per le canzoni",
"TaskDownloadMissingLyrics": "Scarica testi mancanti"
"TaskDownloadMissingLyrics": "Scarica testi mancanti",
"TaskMoveTrickplayImages": "Sposta le immagini Trickplay",
"TaskMoveTrickplayImagesDescription": "Sposta le immagini Trickplay esistenti secondo la configurazione della libreria."
}

View File

@@ -129,5 +129,10 @@
"TaskCleanCollectionsAndPlaylists": "コレクションとプレイリストをクリーンアップ",
"TaskAudioNormalization": "音声の正規化",
"TaskAudioNormalizationDescription": "音声の正規化データのためにファイルをスキャンします。",
"TaskCleanCollectionsAndPlaylistsDescription": "在しなくなったコレクションやプレイリストからアイテムを削除します。"
"TaskCleanCollectionsAndPlaylistsDescription": "在しなくなったコレクションやプレイリストからアイテムを削除します。",
"TaskDownloadMissingLyricsDescription": "歌詞をダウンロード",
"TaskExtractMediaSegments": "メディアセグメントを読み取る",
"TaskMoveTrickplayImages": "Trickplayの画像を移動",
"TaskMoveTrickplayImagesDescription": "ライブラリ設定によりTrickplayのファイルを移動。",
"TaskDownloadMissingLyrics": "記録されていない歌詞をダウンロード"
}

View File

@@ -131,5 +131,9 @@
"TaskCleanCollectionsAndPlaylists": "Glanhe kuntellow ha rolyow-gwari",
"TaskKeyframeExtractor": "Estennell Framalhwedh",
"TaskCleanCollectionsAndPlaylistsDescription": "Y hwra dilea taklow a-dhyworth kuntellow ha rolyow-gwari na vos na moy.",
"TaskKeyframeExtractorDescription": "Y hwra kuntel framyowalhwedh a-dhyworth restrennow gwydhyowyow rag gul rolyow-gwari HLS moy poran. Martesen y hwra an oberen ma ow ponya rag termyn hir."
"TaskKeyframeExtractorDescription": "Y hwra kuntel framyowalhwedh a-dhyworth restrennow gwydhyowyow rag gul rolyow-gwari HLS moy poran. Martesen y hwra an oberen ma ow ponya rag termyn hir.",
"TaskExtractMediaSegments": "Arhwilas Rann Media",
"TaskExtractMediaSegmentsDescription": "Kavos rannow media a-dhyworth ystynansow gallosegys MediaSegment.",
"TaskMoveTrickplayImages": "Divroa Tyller Imach TrickPlay",
"TaskMoveTrickplayImagesDescription": "Y hwra movya restrennow a-lemmyn trickplay herwydh settyansow lyverva."
}

View File

@@ -55,7 +55,7 @@
"Genres": "Жанрови",
"Folders": "Папки",
"Favorites": "Омилени",
"FailedLoginAttemptWithUserName": "Неуспешно поврзување од {0}",
"FailedLoginAttemptWithUserName": "Неуспешен обид за најавување од {0}",
"DeviceOnlineWithName": "{0} е приклучен",
"DeviceOfflineWithName": "{0} се исклучи",
"Collections": "Колекции",
@@ -123,5 +123,13 @@
"TaskCleanActivityLogDescription": "Избришува логови на активности постари од определеното време.",
"TaskCleanActivityLog": "Избриши Лог на Активности",
"External": "Надворешен",
"HearingImpaired": "Оштетен слух"
"HearingImpaired": "Оштетен слух",
"TaskCleanCollectionsAndPlaylists": "Исчисти ги колекциите и плејлистите",
"TaskAudioNormalizationDescription": "Скенирање датотеки за податоци за нормализација на звукот.",
"TaskDownloadMissingLyrics": "Преземи стихови кои недостасуваат",
"TaskDownloadMissingLyricsDescription": "Преземи стихови/текстови за песни",
"TaskRefreshTrickplayImages": "Генерирај слики за прегледување (Trickplay)",
"TaskAudioNormalization": "Нормализација на звукот",
"TaskRefreshTrickplayImagesDescription": "Креира трикплеј прегледи за видеа во овозможените библиотеки.",
"TaskCleanCollectionsAndPlaylistsDescription": "Отстранува ставки од колекциите и плејлистите што веќе не постојат."
}

View File

@@ -128,9 +128,13 @@
"TaskRefreshTrickplayImages": "Generer Trickplay bilder",
"TaskRefreshTrickplayImagesDescription": "Oppretter trickplay-forhåndsvisninger for videoer i aktiverte biblioteker.",
"TaskCleanCollectionsAndPlaylists": "Rydd kolleksjoner og spillelister",
"TaskAudioNormalization": "Lyd Normalisering",
"TaskAudioNormalizationDescription": "Skan filer for lyd normaliserende data",
"TaskCleanCollectionsAndPlaylistsDescription": "Fjerner elementer fra kolleksjoner og spillelister som ikke lengere finnes",
"TaskAudioNormalization": "Lydnormalisering",
"TaskAudioNormalizationDescription": "Skan filer for lydnormaliserende data.",
"TaskCleanCollectionsAndPlaylistsDescription": "Fjerner elementer fra kolleksjoner og spillelister som ikke lengere finnes.",
"TaskDownloadMissingLyrics": "Last ned manglende tekster",
"TaskDownloadMissingLyricsDescription": "Last ned sangtekster"
"TaskDownloadMissingLyricsDescription": "Last ned sangtekster",
"TaskExtractMediaSegments": "Skann mediasegment",
"TaskMoveTrickplayImages": "Migrer bildeplassering for Trickplay",
"TaskMoveTrickplayImagesDescription": "Flytter eksisterende Trickplay-filer i henhold til bibliotekseinstillingene.",
"TaskExtractMediaSegmentsDescription": "Trekker ut eller henter mediasegmenter fra plugins som støtter MediaSegment."
}

View File

@@ -16,13 +16,13 @@
"Folders": "Mappen",
"Genres": "Genres",
"HeaderAlbumArtists": "Albumartiesten",
"HeaderContinueWatching": "Kijken hervatten",
"HeaderContinueWatching": "Verderkijken",
"HeaderFavoriteAlbums": "Favoriete albums",
"HeaderFavoriteArtists": "Favoriete artiesten",
"HeaderFavoriteEpisodes": "Favoriete afleveringen",
"HeaderFavoriteShows": "Favoriete shows",
"HeaderFavoriteShows": "Favoriete series",
"HeaderFavoriteSongs": "Favoriete nummers",
"HeaderLiveTV": "Live TV",
"HeaderLiveTV": "Live-tv",
"HeaderNextUp": "Volgende",
"HeaderRecordingGroups": "Opnamegroepen",
"HomeVideos": "Homevideo's",
@@ -34,8 +34,8 @@
"Latest": "Nieuwste",
"MessageApplicationUpdated": "Jellyfin Server is bijgewerkt",
"MessageApplicationUpdatedTo": "Jellyfin Server is bijgewerkt naar {0}",
"MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de server configuratie is bijgewerkt",
"MessageServerConfigurationUpdated": "Server configuratie is bijgewerkt",
"MessageNamedServerConfigurationUpdatedWithValue": "Sectie {0} van de serverconfiguratie is bijgewerkt",
"MessageServerConfigurationUpdated": "Serverconfiguratie is bijgewerkt",
"MixedContent": "Gemengde inhoud",
"Movies": "Films",
"Music": "Muziek",
@@ -50,12 +50,12 @@
"NotificationOptionAudioPlaybackStopped": "Muziek gestopt",
"NotificationOptionCameraImageUploaded": "Camera-afbeelding geüpload",
"NotificationOptionInstallationFailed": "Installatie mislukt",
"NotificationOptionNewLibraryContent": "Nieuwe content toegevoegd",
"NotificationOptionPluginError": "Plug-in fout",
"NotificationOptionNewLibraryContent": "Nieuwe inhoud toegevoegd",
"NotificationOptionPluginError": "Plug-in-fout",
"NotificationOptionPluginInstalled": "Plug-in geïnstalleerd",
"NotificationOptionPluginUninstalled": "Plug-in verwijderd",
"NotificationOptionPluginUpdateInstalled": "Plug-in-update geïnstalleerd",
"NotificationOptionServerRestartRequired": "Server herstart nodig",
"NotificationOptionServerRestartRequired": "Herstarten server vereist",
"NotificationOptionTaskFailed": "Geplande taak mislukt",
"NotificationOptionUserLockedOut": "Gebruiker is vergrendeld",
"NotificationOptionVideoPlayback": "Afspelen van video gestart",
@@ -72,16 +72,16 @@
"ServerNameNeedsToBeRestarted": "{0} moet herstart worden",
"Shows": "Series",
"Songs": "Nummers",
"StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden, probeer het later opnieuw.",
"StartupEmbyServerIsLoading": "Jellyfin Server is aan het laden. Probeer het later opnieuw.",
"SubtitleDownloadFailureForItem": "Downloaden van ondertiteling voor {0} is mislukt",
"SubtitleDownloadFailureFromForItem": "Ondertitels konden niet gedownload worden van {0} voor {1}",
"SubtitleDownloadFailureFromForItem": "Ondertiteling kon niet gedownload worden van {0} voor {1}",
"Sync": "Synchronisatie",
"System": "Systeem",
"TvShows": "TV-series",
"User": "Gebruiker",
"UserCreatedWithName": "Gebruiker {0} is aangemaakt",
"UserDeletedWithName": "Gebruiker {0} is verwijderd",
"UserDownloadingItemWithValues": "{0} download {1}",
"UserDownloadingItemWithValues": "{0} downloadt {1}",
"UserLockedOutWithName": "Gebruikersaccount {0} is vergrendeld",
"UserOfflineFromDevice": "Verbinding van {0} met {1} is verbroken",
"UserOnlineFromDevice": "{0} heeft verbinding met {1}",
@@ -90,7 +90,7 @@
"UserStartedPlayingItemWithValues": "{0} speelt {1} af op {2}",
"UserStoppedPlayingItemWithValues": "{0} heeft afspelen van {1} gestopt op {2}",
"ValueHasBeenAddedToLibrary": "{0} is toegevoegd aan je mediabibliotheek",
"ValueSpecialEpisodeName": "Speciaal - {0}",
"ValueSpecialEpisodeName": "Special - {0}",
"VersionNumber": "Versie {0}",
"TaskDownloadMissingSubtitlesDescription": "Zoekt op het internet naar ontbrekende ondertiteling gebaseerd op metadataconfiguratie.",
"TaskDownloadMissingSubtitles": "Ontbrekende ondertiteling downloaden",
@@ -132,5 +132,9 @@
"TaskAudioNormalization": "Geluidsnormalisatie",
"TaskAudioNormalizationDescription": "Scant bestanden op gegevens voor geluidsnormalisatie.",
"TaskDownloadMissingLyrics": "Ontbrekende liedteksten downloaden",
"TaskDownloadMissingLyricsDescription": "Downloadt liedteksten"
"TaskDownloadMissingLyricsDescription": "Downloadt liedteksten",
"TaskExtractMediaSegmentsDescription": "Verkrijgt mediasegmenten vanuit plug-ins met MediaSegment-ondersteuning.",
"TaskMoveTrickplayImages": "Locatie trickplay-afbeeldingen migreren",
"TaskMoveTrickplayImagesDescription": "Verplaatst bestaande trickplay-bestanden op basis van de bibliotheekinstellingen.",
"TaskExtractMediaSegments": "Scannen op mediasegmenten"
}

View File

@@ -132,5 +132,9 @@
"TaskAudioNormalization": "Normalizacja dźwięku",
"TaskAudioNormalizationDescription": "Skanuje pliki w poszukiwaniu danych normalizacji dźwięku.",
"TaskDownloadMissingLyrics": "Pobierz brakujące słowa",
"TaskDownloadMissingLyricsDescription": "Pobierz słowa piosenek"
"TaskDownloadMissingLyricsDescription": "Pobierz słowa piosenek",
"TaskExtractMediaSegments": "Skanowanie segmentów mediów",
"TaskMoveTrickplayImages": "Migruj lokalizację obrazu Trickplay",
"TaskExtractMediaSegmentsDescription": "Wyodrębnia lub pobiera segmenty mediów z wtyczek obsługujących MediaSegment.",
"TaskMoveTrickplayImagesDescription": "Przenosi istniejące pliki Trickplay zgodnie z ustawieniami biblioteki."
}

View File

@@ -8,7 +8,7 @@
"CameraImageUploadedFrom": "Uma nova imagem da câmera foi enviada de {0}",
"Channels": "Canais",
"ChapterNameValue": "Capítulo {0}",
"Collections": "Coletâneas",
"Collections": "Coleções",
"DeviceOfflineWithName": "{0} se desconectou",
"DeviceOnlineWithName": "{0} se conectou",
"FailedLoginAttemptWithUserName": "Falha na tentativa de login de {0}",
@@ -130,5 +130,11 @@
"TaskCleanCollectionsAndPlaylists": "Limpe coleções e playlists",
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e playlists que não existem mais.",
"TaskAudioNormalization": "Normalização de áudio",
"TaskAudioNormalizationDescription": "Examina os ficheiros em busca de dados de normalização de áudio."
"TaskAudioNormalizationDescription": "Examina os ficheiros em busca de dados de normalização de áudio.",
"TaskDownloadMissingLyricsDescription": "Baixar letras para músicas",
"TaskDownloadMissingLyrics": "Baixar letra faltante",
"TaskMoveTrickplayImagesDescription": "Move os arquivos do trickplay de acordo com as configurações da biblioteca.",
"TaskExtractMediaSegments": "Varredura do segmento de mídia",
"TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos de mídia de plug-ins habilitados para MediaSegment.",
"TaskMoveTrickplayImages": "Migrar o local da imagem do Trickplay"
}

View File

@@ -129,5 +129,11 @@
"TaskCleanCollectionsAndPlaylistsDescription": "Remove itens de coleções e listas de reprodução que já não existem.",
"TaskCleanCollectionsAndPlaylists": "Limpar coleções e listas de reprodução",
"TaskAudioNormalizationDescription": "Analisa os ficheiros para obter dados de normalização de áudio.",
"TaskAudioNormalization": "Normalização de áudio"
"TaskAudioNormalization": "Normalização de áudio",
"TaskDownloadMissingLyrics": "Baixar letras faltantes",
"TaskDownloadMissingLyricsDescription": "Baixa letras para músicas",
"TaskMoveTrickplayImagesDescription": "Transfere ficheiros de miniatura de vídeo, conforme as definições da biblioteca.",
"TaskExtractMediaSegments": "Varrimento de segmentos da média",
"TaskExtractMediaSegmentsDescription": "Extrai ou obtém segmentos de média de extensões com suporte a MediaSegment.",
"TaskMoveTrickplayImages": "Migração de miniaturas de vídeo"
}

View File

@@ -129,5 +129,11 @@
"TaskAudioNormalizationDescription": "Scanează fișiere pentru date necesare normalizării sunetului.",
"TaskAudioNormalization": "Normalizare sunet",
"TaskCleanCollectionsAndPlaylists": "Curăță colecțiile și listele de redare",
"TaskCleanCollectionsAndPlaylistsDescription": "Elimină elementele care nu mai există din colecții și liste de redare."
"TaskCleanCollectionsAndPlaylistsDescription": "Elimină elementele care nu mai există din colecții și liste de redare.",
"TaskExtractMediaSegments": "Scanează segmentele media",
"TaskMoveTrickplayImagesDescription": "Mută fișierele trickplay existente conform setărilor librăriei.",
"TaskExtractMediaSegmentsDescription": "Extrage sau obține segmentele media de la pluginurile MediaSegment activate.",
"TaskMoveTrickplayImages": "Migrează locația imaginii Trickplay",
"TaskDownloadMissingLyrics": "Descarcă versurile lipsă",
"TaskDownloadMissingLyricsDescription": "Descarcă versuri pentru melodii"
}

View File

@@ -130,5 +130,11 @@
"TaskCleanCollectionsAndPlaylists": "Vyčistiť kolekcie a playlisty",
"TaskCleanCollectionsAndPlaylistsDescription": "Odstráni položky z kolekcií a playlistov, ktoré už neexistujú.",
"TaskAudioNormalization": "Normalizácia zvuku",
"TaskAudioNormalizationDescription": "Skenovať súbory za účelom normalizácie zvuku."
"TaskAudioNormalizationDescription": "Skenovať súbory za účelom normalizácie zvuku.",
"TaskExtractMediaSegments": "Skenovanie segmentov médií",
"TaskExtractMediaSegmentsDescription": "Extrahuje alebo získava segmenty médií zo zásuvných modulov s povolenou funkciou MediaSegment.",
"TaskMoveTrickplayImages": "Presunúť umiestnenie obrázkov Trickplay",
"TaskMoveTrickplayImagesDescription": "Presunie existujúce súbory Trickplay podľa nastavení knižnice.",
"TaskDownloadMissingLyrics": "Stiahnuť chýbajúce texty piesní",
"TaskDownloadMissingLyricsDescription": "Stiahne texty pre piesne"
}

View File

@@ -3,7 +3,7 @@
"AppDeviceValues": "Aplikacija: {0}, Naprava: {1}",
"Application": "Aplikacija",
"Artists": "Izvajalci",
"AuthenticationSucceededWithUserName": "{0} se je uspešno prijavil",
"AuthenticationSucceededWithUserName": "{0} se je uspešno prijavil/a",
"Books": "Knjige",
"CameraImageUploadedFrom": "Nova fotografija je bila naložena iz {0}",
"Channels": "Kanali",

View File

@@ -9,7 +9,7 @@
"Channels": "Kanaler",
"ChapterNameValue": "Kapitel {0}",
"Collections": "Samlingar",
"DeviceOfflineWithName": "{0} har avbrutit uppkopplingen",
"DeviceOfflineWithName": "{0} har kopplat ned",
"DeviceOnlineWithName": "{0} är ansluten",
"FailedLoginAttemptWithUserName": "Misslyckat inloggningsförsök från {0}",
"Favorites": "Favoriter",
@@ -121,7 +121,7 @@
"Default": "Standard",
"TaskOptimizeDatabase": "Optimera databasen",
"TaskOptimizeDatabaseDescription": "Komprimerar databasen och trunkerar ledigt utrymme. Prestandan kan förbättras genom att köra denna aktivitet efter att du har skannat biblioteket eller gjort andra förändringar som indikerar att databasen har modifierats.",
"TaskKeyframeExtractorDescription": "Exporterar nyckelbildrutor från videofiler för att skapa mer exakta HLS-spellistor. Denna rutin kan ta lång tid.",
"TaskKeyframeExtractorDescription": "Exporterar nyckelbildrutor från videofiler för att skapa mer exakta HLS-spellistor. Denna körning kan ta lång tid.",
"TaskKeyframeExtractor": "Extraktor för nyckelbildrutor",
"External": "Extern",
"HearingImpaired": "Hörselskadad",
@@ -132,5 +132,9 @@
"TaskCleanCollectionsAndPlaylistsDescription": "Tar bort objekt från samlingar och spellistor som inte längre finns.",
"TaskAudioNormalizationDescription": "Skannar filer för ljudnormaliseringsdata.",
"TaskDownloadMissingLyrics": "Ladda ner saknad låttext",
"TaskDownloadMissingLyricsDescription": "Laddar ner låttexter"
"TaskDownloadMissingLyricsDescription": "Laddar ner låttexter",
"TaskExtractMediaSegments": "Skanning av mediesegment",
"TaskExtractMediaSegmentsDescription": "Extraherar eller hämtar ut mediesegmen från tillägg som stöder MediaSegment.",
"TaskMoveTrickplayImages": "Migrera platsen för Trickplay-bilder",
"TaskMoveTrickplayImagesDescription": "Flyttar befintliga trickplay-filer enligt bibliotekets inställningar."
}

View File

@@ -130,5 +130,11 @@
"TaskCleanCollectionsAndPlaylistsDescription": "Artık var olmayan koleksiyon ve çalma listelerindeki ögeleri kaldırır.",
"TaskCleanCollectionsAndPlaylists": "Koleksiyonları ve çalma listelerini temizleyin",
"TaskAudioNormalizationDescription": "Ses normalleştirme verileri için dosyaları tarar.",
"TaskAudioNormalization": "Ses Normalleştirme"
"TaskAudioNormalization": "Ses Normalleştirme",
"TaskExtractMediaSegments": "Medya Segmenti Tarama",
"TaskMoveTrickplayImages": "Trickplay Görsel Konumunu Taşıma",
"TaskMoveTrickplayImagesDescription": "Mevcut trickplay dosyalarını kütüphane ayarlarına göre taşır.",
"TaskDownloadMissingLyrics": "Eksik şarkı sözlerini indir",
"TaskDownloadMissingLyricsDescription": "Şarkı sözlerini indirir",
"TaskExtractMediaSegmentsDescription": "MediaSegment özelliği etkin olan eklentilerden medya segmentlerini çıkarır veya alır."
}

View File

@@ -131,5 +131,9 @@
"TaskAudioNormalizationDescription": "Сканує файли на наявність даних для нормалізації звуку.",
"TaskAudioNormalization": "Нормалізація аудіо",
"TaskDownloadMissingLyrics": "Завантажити відсутні тексти пісень",
"TaskDownloadMissingLyricsDescription": "Завантаження текстів пісень"
"TaskDownloadMissingLyricsDescription": "Завантаження текстів пісень",
"TaskMoveTrickplayImagesDescription": "Переміщує наявні Trickplay-зображення відповідно до налаштувань медіатеки.",
"TaskExtractMediaSegments": "Сканування медіа-сегментів",
"TaskMoveTrickplayImages": "Змінити місце розташування Trickplay-зображень",
"TaskExtractMediaSegmentsDescription": "Витягує або отримує медіа-сегменти з плагінів з підтримкою MediaSegment."
}

View File

@@ -131,5 +131,9 @@
"TaskAudioNormalization": "Chuẩn Hóa Âm Thanh",
"TaskAudioNormalizationDescription": "Quét tập tin để tìm dữ liệu chuẩn hóa âm thanh.",
"TaskDownloadMissingLyricsDescription": "Tải xuống lời cho bài hát",
"TaskDownloadMissingLyrics": "Tải xuống lời bị thiếu"
"TaskDownloadMissingLyrics": "Tải xuống lời bị thiếu",
"TaskExtractMediaSegmentsDescription": "Trích xuất hoặc lấy các phân đoạn phương tiện từ các plugin hỗ trợ MediaSegment.",
"TaskMoveTrickplayImages": "Di chuyển vị trí hình ảnh Trickplay",
"TaskMoveTrickplayImagesDescription": "Di chuyển các tập tin trickplay hiện có theo cài đặt thư viện.",
"TaskExtractMediaSegments": "Quét Phân Đoạn Phương Tiện"
}

View File

@@ -93,7 +93,7 @@
"ValueSpecialEpisodeName": "特典 - {0}",
"VersionNumber": "版本 {0}",
"TaskUpdatePluginsDescription": "为已设置为自动更新的插件下载和安装更新。",
"TaskRefreshPeople": "刷新人员",
"TaskRefreshPeople": "刷新演职人员",
"TasksChannelsCategory": "互联网频道",
"TasksLibraryCategory": "媒体库",
"TaskDownloadMissingSubtitlesDescription": "根据元数据设置在互联网上搜索缺少的字幕。",
@@ -122,15 +122,19 @@
"TaskOptimizeDatabaseDescription": "压缩数据库并优化可用空间,在扫描库或执行其他数据库修改后运行此任务可能会提高性能。",
"TaskOptimizeDatabase": "优化数据库",
"TaskKeyframeExtractorDescription": "从视频文件中提取关键帧以创建更准确的 HLS 播放列表。这项任务可能需要很长时间。",
"TaskKeyframeExtractor": "关键帧提取",
"TaskKeyframeExtractor": "关键帧提取",
"External": "外部",
"HearingImpaired": "听力障碍",
"TaskRefreshTrickplayImages": "生成时间轴缩略图",
"TaskRefreshTrickplayImagesDescription": "为启用的媒体库中的视频生成时间轴缩略图。",
"TaskRefreshTrickplayImages": "生成进度条预览图",
"TaskRefreshTrickplayImagesDescription": "为启用的媒体库中的视频生成进度条预览图。",
"TaskCleanCollectionsAndPlaylists": "清理合集和播放列表",
"TaskCleanCollectionsAndPlaylistsDescription": "清理合集和播放列表中已不存在的项目。",
"TaskAudioNormalization": "音频标准化",
"TaskAudioNormalizationDescription": "扫描文件以寻找音频标准化数据。",
"TaskDownloadMissingLyrics": "下载缺失的歌词",
"TaskDownloadMissingLyricsDescription": "下载歌曲歌词"
"TaskDownloadMissingLyricsDescription": "下载歌曲歌词",
"TaskMoveTrickplayImages": "迁移进度条预览图的存储位置",
"TaskExtractMediaSegments": "媒体片段扫描",
"TaskExtractMediaSegmentsDescription": "从支持 MediaSegment 的插件中提取或获取媒体片段。",
"TaskMoveTrickplayImagesDescription": "根据媒体库设置移动现有的进度条预览图文件。"
}

View File

@@ -129,5 +129,11 @@
"TaskCleanCollectionsAndPlaylists": "清理系列和播放清單",
"TaskCleanCollectionsAndPlaylistsDescription": "清理系列和播放清單中已不存在的項目。",
"TaskAudioNormalization": "音量標準化",
"TaskAudioNormalizationDescription": "掃描文件以找出音量標準化資料。"
"TaskAudioNormalizationDescription": "掃描文件以找出音量標準化資料。",
"TaskDownloadMissingLyrics": "下載缺少的歌詞",
"TaskDownloadMissingLyricsDescription": "卡在歌曲歌詞",
"TaskExtractMediaSegments": "掃描媒體片段",
"TaskExtractMediaSegmentsDescription": "從使用媒體片段的擴充功能取得媒體片段。",
"TaskMoveTrickplayImages": "遷移快轉縮圖位置",
"TaskMoveTrickplayImagesDescription": "根據媒體庫的設定遷移快轉縮圖的檔案。"
}

View File

@@ -91,8 +91,29 @@ namespace Emby.Server.Implementations.MediaEncoder
return video.DefaultVideoStreamIndex.HasValue;
}
private long GetAverageDurationBetweenChapters(IReadOnlyList<ChapterInfo> chapters)
{
if (chapters.Count < 2)
{
return 0;
}
long sum = 0;
for (int i = 1; i < chapters.Count; i++)
{
sum += chapters[i].StartPositionTicks - chapters[i - 1].StartPositionTicks;
}
return sum / chapters.Count;
}
public async Task<bool> RefreshChapterImages(Video video, IDirectoryService directoryService, IReadOnlyList<ChapterInfo> chapters, bool extractImages, bool saveChapters, CancellationToken cancellationToken)
{
if (chapters.Count == 0)
{
return true;
}
var libraryOptions = _libraryManager.GetLibraryOptions(video);
if (!IsEligibleForChapterImageExtraction(video, libraryOptions))
@@ -100,6 +121,14 @@ namespace Emby.Server.Implementations.MediaEncoder
extractImages = false;
}
var averageChapterDuration = GetAverageDurationBetweenChapters(chapters);
var threshold = TimeSpan.FromSeconds(1).Ticks;
if (averageChapterDuration < threshold)
{
_logger.LogInformation("Skipping chapter image extraction for {Video} as the average chapter duration {AverageDuration} was lower than the minimum threshold {Threshold}", video.Name, averageChapterDuration, threshold);
extractImages = false;
}
var success = true;
var changesMade = false;

View File

@@ -0,0 +1,118 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using Jellyfin.Data.Enums;
using MediaBrowser.Controller;
using MediaBrowser.Controller.Dto;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Globalization;
using MediaBrowser.Model.Tasks;
namespace Emby.Server.Implementations.ScheduledTasks.Tasks;
/// <summary>
/// Task to obtain media segments.
/// </summary>
public class MediaSegmentExtractionTask : IScheduledTask
{
/// <summary>
/// The library manager.
/// </summary>
private readonly ILibraryManager _libraryManager;
private readonly ILocalizationManager _localization;
private readonly IMediaSegmentManager _mediaSegmentManager;
private static readonly BaseItemKind[] _itemTypes = [BaseItemKind.Episode, BaseItemKind.Movie, BaseItemKind.Audio, BaseItemKind.AudioBook];
/// <summary>
/// Initializes a new instance of the <see cref="MediaSegmentExtractionTask" /> class.
/// </summary>
/// <param name="libraryManager">The library manager.</param>
/// <param name="localization">The localization manager.</param>
/// <param name="mediaSegmentManager">The segment manager.</param>
public MediaSegmentExtractionTask(ILibraryManager libraryManager, ILocalizationManager localization, IMediaSegmentManager mediaSegmentManager)
{
_libraryManager = libraryManager;
_localization = localization;
_mediaSegmentManager = mediaSegmentManager;
}
/// <inheritdoc/>
public string Name => _localization.GetLocalizedString("TaskExtractMediaSegments");
/// <inheritdoc/>
public string Description => _localization.GetLocalizedString("TaskExtractMediaSegmentsDescription");
/// <inheritdoc/>
public string Category => _localization.GetLocalizedString("TasksLibraryCategory");
/// <inheritdoc/>
public string Key => "TaskExtractMediaSegments";
/// <inheritdoc/>
public async Task ExecuteAsync(IProgress<double> progress, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
progress.Report(0);
var pagesize = 100;
var query = new InternalItemsQuery
{
MediaTypes = new[] { MediaType.Video, MediaType.Audio },
IsVirtualItem = false,
IncludeItemTypes = _itemTypes,
DtoOptions = new DtoOptions(true),
SourceTypes = new[] { SourceType.Library },
Recursive = true,
Limit = pagesize
};
var numberOfVideos = _libraryManager.GetCount(query);
var startIndex = 0;
var numComplete = 0;
while (startIndex < numberOfVideos)
{
query.StartIndex = startIndex;
var baseItems = _libraryManager.GetItemList(query);
var currentPageCount = baseItems.Count;
// TODO parallelize with Parallel.ForEach?
for (var i = 0; i < currentPageCount; i++)
{
cancellationToken.ThrowIfCancellationRequested();
var item = baseItems[i];
// Only local files supported
if (item.IsFileProtocol && File.Exists(item.Path))
{
await _mediaSegmentManager.RunSegmentPluginProviders(item, false, cancellationToken).ConfigureAwait(false);
}
// Update progress
numComplete++;
double percent = (double)numComplete / numberOfVideos;
progress.Report(100 * percent);
}
startIndex += pagesize;
}
progress.Report(100);
}
/// <inheritdoc/>
public IEnumerable<TaskTriggerInfo> GetDefaultTriggers()
{
yield return new TaskTriggerInfo
{
Type = TaskTriggerInfo.TriggerInterval,
IntervalTicks = TimeSpan.FromHours(12).Ticks
};
}
}

View File

@@ -1,7 +1,5 @@
#nullable disable
#pragma warning disable CS1591
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
@@ -68,13 +66,29 @@ namespace Emby.Server.Implementations.Session
private Timer _inactiveTimer;
private DtoOptions _itemInfoDtoOptions;
private bool _disposed = false;
private bool _disposed;
/// <summary>
/// Initializes a new instance of the <see cref="SessionManager"/> class.
/// </summary>
/// <param name="logger">Instance of <see cref="ILogger{SessionManager}"/> interface.</param>
/// <param name="eventManager">Instance of <see cref="IEventManager"/> interface.</param>
/// <param name="userDataManager">Instance of <see cref="IUserDataManager"/> interface.</param>
/// <param name="serverConfigurationManager">Instance of <see cref="IServerConfigurationManager"/> interface.</param>
/// <param name="libraryManager">Instance of <see cref="ILibraryManager"/> interface.</param>
/// <param name="userManager">Instance of <see cref="IUserManager"/> interface.</param>
/// <param name="musicManager">Instance of <see cref="IMusicManager"/> interface.</param>
/// <param name="dtoService">Instance of <see cref="IDtoService"/> interface.</param>
/// <param name="imageProcessor">Instance of <see cref="IImageProcessor"/> interface.</param>
/// <param name="appHost">Instance of <see cref="IServerApplicationHost"/> interface.</param>
/// <param name="deviceManager">Instance of <see cref="IDeviceManager"/> interface.</param>
/// <param name="mediaSourceManager">Instance of <see cref="IMediaSourceManager"/> interface.</param>
/// <param name="hostApplicationLifetime">Instance of <see cref="IHostApplicationLifetime"/> interface.</param>
public SessionManager(
ILogger<SessionManager> logger,
IEventManager eventManager,
IUserDataManager userDataManager,
IServerConfigurationManager config,
IServerConfigurationManager serverConfigurationManager,
ILibraryManager libraryManager,
IUserManager userManager,
IMusicManager musicManager,
@@ -88,7 +102,7 @@ namespace Emby.Server.Implementations.Session
_logger = logger;
_eventManager = eventManager;
_userDataManager = userDataManager;
_config = config;
_config = serverConfigurationManager;
_libraryManager = libraryManager;
_userManager = userManager;
_musicManager = musicManager;
@@ -508,7 +522,10 @@ namespace Emby.Server.Implementations.Session
deviceName = "Network Device";
}
var deviceOptions = _deviceManager.GetDeviceOptions(deviceId);
var deviceOptions = _deviceManager.GetDeviceOptions(deviceId) ?? new()
{
DeviceId = deviceId
};
if (string.IsNullOrEmpty(deviceOptions.CustomName))
{
sessionInfo.DeviceName = deviceName;
@@ -1076,6 +1093,42 @@ namespace Emby.Server.Implementations.Session
return session;
}
private SessionInfoDto ToSessionInfoDto(SessionInfo sessionInfo)
{
return new SessionInfoDto
{
PlayState = sessionInfo.PlayState,
AdditionalUsers = sessionInfo.AdditionalUsers,
Capabilities = _deviceManager.ToClientCapabilitiesDto(sessionInfo.Capabilities),
RemoteEndPoint = sessionInfo.RemoteEndPoint,
PlayableMediaTypes = sessionInfo.PlayableMediaTypes,
Id = sessionInfo.Id,
UserId = sessionInfo.UserId,
UserName = sessionInfo.UserName,
Client = sessionInfo.Client,
LastActivityDate = sessionInfo.LastActivityDate,
LastPlaybackCheckIn = sessionInfo.LastPlaybackCheckIn,
LastPausedDate = sessionInfo.LastPausedDate,
DeviceName = sessionInfo.DeviceName,
DeviceType = sessionInfo.DeviceType,
NowPlayingItem = sessionInfo.NowPlayingItem,
NowViewingItem = sessionInfo.NowViewingItem,
DeviceId = sessionInfo.DeviceId,
ApplicationVersion = sessionInfo.ApplicationVersion,
TranscodingInfo = sessionInfo.TranscodingInfo,
IsActive = sessionInfo.IsActive,
SupportsMediaControl = sessionInfo.SupportsMediaControl,
SupportsRemoteControl = sessionInfo.SupportsRemoteControl,
NowPlayingQueue = sessionInfo.NowPlayingQueue,
NowPlayingQueueFullItems = sessionInfo.NowPlayingQueueFullItems,
HasCustomDeviceName = sessionInfo.HasCustomDeviceName,
PlaylistItemId = sessionInfo.PlaylistItemId,
ServerId = sessionInfo.ServerId,
UserPrimaryImageTag = sessionInfo.UserPrimaryImageTag,
SupportedCommands = sessionInfo.SupportedCommands
};
}
/// <inheritdoc />
public Task SendMessageCommand(string controllingSessionId, string sessionId, MessageCommand command, CancellationToken cancellationToken)
{
@@ -1393,7 +1446,7 @@ namespace Emby.Server.Implementations.Session
UserName = user.Username
};
session.AdditionalUsers = [..session.AdditionalUsers, newUser];
session.AdditionalUsers = [.. session.AdditionalUsers, newUser];
}
}
@@ -1505,7 +1558,7 @@ namespace Emby.Server.Implementations.Session
var returnResult = new AuthenticationResult
{
User = _userManager.GetUserDto(user, request.RemoteEndPoint),
SessionInfo = session,
SessionInfo = ToSessionInfoDto(session),
AccessToken = token,
ServerId = _appHost.SystemId
};
@@ -1800,6 +1853,105 @@ namespace Emby.Server.Implementations.Session
return await GetSessionByAuthenticationToken(items[0], deviceId, remoteEndpoint, null).ConfigureAwait(false);
}
/// <inheritdoc/>
public IReadOnlyList<SessionInfoDto> GetSessions(
Guid userId,
string deviceId,
int? activeWithinSeconds,
Guid? controllableUserToCheck,
bool isApiKey)
{
var result = Sessions;
if (!string.IsNullOrEmpty(deviceId))
{
result = result.Where(i => string.Equals(i.DeviceId, deviceId, StringComparison.OrdinalIgnoreCase));
}
var userCanControlOthers = false;
var userIsAdmin = false;
User user = null;
if (isApiKey)
{
userCanControlOthers = true;
userIsAdmin = true;
}
else if (!userId.IsEmpty())
{
user = _userManager.GetUserById(userId);
if (user is not null)
{
userCanControlOthers = user.HasPermission(PermissionKind.EnableRemoteControlOfOtherUsers);
userIsAdmin = user.HasPermission(PermissionKind.IsAdministrator);
}
else
{
return [];
}
}
if (!controllableUserToCheck.IsNullOrEmpty())
{
result = result.Where(i => i.SupportsRemoteControl);
var controlledUser = _userManager.GetUserById(controllableUserToCheck.Value);
if (controlledUser is null)
{
return [];
}
if (!controlledUser.HasPermission(PermissionKind.EnableSharedDeviceControl))
{
// Controlled user has device sharing disabled
result = result.Where(i => !i.UserId.IsEmpty());
}
if (!userCanControlOthers)
{
// User cannot control other user's sessions, validate user id.
result = result.Where(i => i.UserId.IsEmpty() || i.ContainsUser(userId));
}
result = result.Where(i =>
{
if (isApiKey)
{
return true;
}
if (user is null)
{
return false;
}
return string.IsNullOrWhiteSpace(i.DeviceId) || _deviceManager.CanAccessDevice(user, i.DeviceId);
});
}
else if (!userIsAdmin)
{
// Request isn't from administrator, limit to "own" sessions.
result = result.Where(i => i.UserId.IsEmpty() || i.ContainsUser(userId));
}
if (!userIsAdmin)
{
// Don't report acceleration type for non-admin users.
result = result.Select(r =>
{
r.TranscodingInfo.HardwareAccelerationType = HardwareAccelerationType.none;
return r;
});
}
if (activeWithinSeconds.HasValue && activeWithinSeconds.Value > 0)
{
var minActiveDate = DateTime.UtcNow.AddSeconds(0 - activeWithinSeconds.Value);
result = result.Where(i => i.LastActivityDate >= minActiveDate);
}
return result.Select(ToSessionInfoDto).ToList();
}
/// <inheritdoc />
public Task SendMessageToAdminSessions<T>(SessionMessageType name, T data, CancellationToken cancellationToken)
{