yocker 1247 Posted May 23, 2025 Author Posted May 23, 2025 (edited) Here is a beta release if any one want to test it. Basically added a scheduled task option to refresh the icons. This should fix the problem of some icons not being added or removed when language changes in files. When for example subtitles are added. The plugin isn't magic ( ) so Emby needs to scan the files it self before it knowns anything has changed. The plugin goes on not knowing about this as there for needs a scheduled task for it to look for changes. I haven't found a way to make it reacts to changes in Emby for that yet. Either it's not possible or i'm just dumb. TLDR: Play around with the scheduled task and see if it works for refreshing and adding/removing icons. BETA! BETA! BETA! BETA! BETA! BETA! Please use in a test environment! @Neminem I hate to keep asking you but, you are usually willing to test. EmbyIcons.dll Edited May 23, 2025 by yocker
Neminem 1518 Posted May 23, 2025 Posted May 23, 2025 @yockerI will see if I get the time today. Otherwise I will give it a go tomorrow.
mickle026 650 Posted May 23, 2025 Posted May 23, 2025 5 hours ago, yocker said: Here is a beta release if any one want to test it. Basically added a scheduled task option to refresh the icons. This should fix the problem of some icons not being added or removed when language changes in files. When for example subtitles are added. The plugin isn't magic ( ) so Emby needs to scan the files it self before it knowns anything has changed. The plugin goes on not knowing about this as there for needs a scheduled task for it to look for changes. I haven't found a way to make it reacts to changes in Emby for that yet. Either it's not possible or i'm just dumb. TLDR: Play around with the scheduled task and see if it works for refreshing and adding/removing icons. BETA! BETA! BETA! BETA! BETA! BETA! Please use in a test environment! @Neminem I hate to keep asking you but, you are usually willing to test. EmbyIcons.dll 1.54 MB · 0 downloads Its a bit of a hack, but I use IMetadata saver for anything like that, basically an adaption of the nfo writer that's triggered when anything changes to the metadata, you can of course trigger it for other things instead. I think there is probably something else that triggers, but don't know what so I use this, it gets triggered every time there's a library scan or an individual item scan or metadata refresh etc. The only down side is that it appears in library options as a saver and has to be turned on. Where it goes into a save just use that to trigger something else public static string SaverName { // here is the name that appears in the Emby Library get { return "Local Moviedata Saver"; } } public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) { // return true, it is enabled for BaseItem and is Movie if (item is Movie) { return true; } return false; } public Task Save(BaseItem item, LibraryOptions libraryOptions, CancellationToken cancellationToken) { I don't know if this info will help or fit your needs, but I mention it because its an alternative.
yocker 1247 Posted May 23, 2025 Author Posted May 23, 2025 (edited) New version up. IMPORTANT!!!! Please use this one instead of the last version (1.21) as a possible crash might happen in that. Also: Added: Button in settings made only to refresh the overlays. Move the number up or down and press save. Note: I'm looking into making this a scheduled task. Edited May 23, 2025 by yocker
yocker 1247 Posted May 23, 2025 Author Posted May 23, 2025 (edited) For those that want to test: Here is another beta. Want to be sure it's stable before releasing it. Whats changed: Moved over to fully using Emby own detection for audio and subtitles. - Used to use ffprobe for external subtitles as it was a fast way of getting it to work. Added a schedule task for refreshing icons. - This might be needed when files have changed, added or removed for icons to reflect any changes. EmbyIcons.dll Code.zip Edited May 23, 2025 by yocker
yocker 1247 Posted May 23, 2025 Author Posted May 23, 2025 (edited) 7 hours ago, mickle026 said: Its a bit of a hack, but I use IMetadata saver for anything like that, basically an adaption of the nfo writer that's triggered when anything changes to the metadata, you can of course trigger it for other things instead. I think there is probably something else that triggers, but don't know what so I use this, it gets triggered every time there's a library scan or an individual item scan or metadata refresh etc. The only down side is that it appears in library options as a saver and has to be turned on. Where it goes into a save just use that to trigger something else public static string SaverName { // here is the name that appears in the Emby Library get { return "Local Moviedata Saver"; } } public bool IsEnabledFor(BaseItem item, ItemUpdateType updateType) { // return true, it is enabled for BaseItem and is Movie if (item is Movie) { return true; } return false; } public Task Save(BaseItem item, LibraryOptions libraryOptions, CancellationToken cancellationToken) { I don't know if this info will help or fit your needs, but I mention it because its an alternative. That looks awesome! I really, really appreciate it!! but i must admit i think i'm starting to get out of my debts here. This was meant as a way to learn to code and oh boy what a project to start with! I tried a fast and dirty version with your suggestion but couldn't get it to work with my cache clearing. Basically as it is now i can only get icons to refresh when new settings are written and the old old made void. I have made a "band aid" fix for that with a scheduled task and it works. If you are willing you are more than welcome to see if you can make it work better. I would be in eternal debt and would do anything to thank you if you did! All i want now is just a fully working plugin that people will be happy about using! Sorry.. That ended up a little like a rant but i really needed to vent my frustrations after smashing my head againts this problem i have encountered. Turns out showing overlays is easy, the rest is f'ing hard for me. Edited May 23, 2025 by yocker
keitaro26 22 Posted May 23, 2025 Posted May 23, 2025 48 minutes ago, yocker said: For those that want to test: Here is another beta. Want to be sure it's stable before releasing it. Whats changed: Moved over to fully using Emby own detection for audio and subtitles. - Used to use ffprobe for external subtitles as it was a fast way of getting it to work. Added a schedule task for refreshing icons. - This might be needed when files have changed, added or removed for icons to reflect any changes. EmbyIcons.dll 1.54 MB · 0 downloads Code.zip 1.51 MB · 0 downloads I can confirm that the beta loads images much faster for me than the current version! 1
Neminem 1518 Posted May 24, 2025 Posted May 24, 2025 @yockerI will have to push testing your plugin, in to the future. I'm seeing some issues with my Beta server install, where it's keeps using more and more RAM. I have removed you plugin and all other plugins that are not on by default, to see if its something in Beta, that's eating my memory. 1
mickle026 650 Posted May 24, 2025 Posted May 24, 2025 A solution for you, not perfect but will work fine in your app. @yockerAdd memory pressure at the start of your loops using parallel functions and release it at the end (or any List type loops and Linq Where(f => f) ) (for a test you can add it at the start of your main program entry and release it when you leave, although I would only add it where you have loops or incrementing lists) This is not a perfect solution but will limit memory usage, and heavy consumption of List Type objects (Dictionary's, Hash sets and Lists),The best way is to empty them, dispose of them, reduce the size as you go. For your application, I very much doubt it will cause any significant speed impact just to force its usage into a managed limit.. What this does is it will allocate a certain size of memory for the objects that use a lot and keep it limited by telling the memory manager to watch this function (quite aggressively) and keep its memory usage cleaned up and reuse the space, rather that let it build up and up and up cleaning it periodically, probably after the function has finished and a huge amount has been consumed already.. long memoryUsed = GC.GetTotalMemory(false); GC.AddMemoryPressure(memoryUsed); Stopwatch memoryTest = Stopwatch.StartNew(); . . . <you code in here> Your logger -- periodically log memory useage by itterations or time . . . Your logger -- "Total execution time: {stopwatch.ElapsedMilliseconds} ms" memoryTest.Stop(); GC.RemoveMemoryPressure(memoryUsed); You can see how much your app is using via logging it. Memory used: {memoryUsed / 1024 / 1024} MB I suggest you test it, run it with it on, then run it with it off, Add a stopwatch and test the speed difference. Hope this helps
yocker 1247 Posted May 24, 2025 Author Posted May 24, 2025 (edited) I think it's official now. Emby was no made with the idea of having the TV show posters overlayed with icons. The only thing i can do that works is simply to refresh the whole cache. So either the clear as a schedule task stays or i will have to remove the TV show poster feature. Edited May 24, 2025 by yocker
bakes82 167 Posted May 24, 2025 Posted May 24, 2025 2 hours ago, yocker said: Emby was no made with the idea of having the TV show posters overlayed with icons. I dont think emby cares, at the end of the day its just an image file.... I dont understand what your issue is, why and what are you caching? Also why not just hook into the LibraryManager ItemUpdated/ItemAdded events in the ServerEntryPoint. Id assume you can then trigger your logic from there? private void LibraryItemAdded(object sender, ItemChangeEventArgs e) { throw new NotImplementedException(); }
yocker 1247 Posted May 24, 2025 Author Posted May 24, 2025 21 minutes ago, bakes82 said: I dont think emby cares, at the end of the day its just an image file.... I dont understand what your issue is, why and what are you caching? Also why not just hook into the LibraryManager ItemUpdated/ItemAdded events in the ServerEntryPoint. Id assume you can then trigger your logic from there? private void LibraryItemAdded(object sender, ItemChangeEventArgs e) { throw new NotImplementedException(); } I'm trying to get TV show posters to get redrawn when a changes has happened to TV episodes so that the icons on the TV show poster will reflect what audio and subtitles are available. I might be totally wrong on this (beginner at programming.) but TV Show posters seems to be aggressively cashed by Emby so can't be singled out and have them redrawn. Think i already tried that, can't remember at this point. Might as well try again.
bakes82 167 Posted May 24, 2025 Posted May 24, 2025 Are you triggering that you updated the metadata? await baseItem.RefreshMetadata(metadataOptions, CancellationToken.None); //You can call this to pull fresh data but not replace images in the options _libraryManager.UpdateItem(baseItem, baseItem.Parent, ItemUpdateType.ImageUpdate);
akacharos 31 Posted May 25, 2025 Posted May 25, 2025 (edited) I feel kinda dumb as I can't get the flag icons to appear in my library (running EmbyIcons 1.19.0.0). Settings are like this: I've put the icons filename that I want (gre,eng) both in 2 letter and 3 letter filename format -just to be on the same side. I run the task in scheduler, I waited, check the log and it's processing the subtitles and audio streams fine. Tried to refresh the metadata on these libraries just to make sure....no subtitle flag icon overlay anywhere. What am I missing here? Edited May 25, 2025 by akacharos 1
akacharos 31 Posted May 25, 2025 Posted May 25, 2025 one suggestion for the logging by the way: Add the itemID for each log entry if possible. Currently is not helping much in troubleshooting without it as we can't check which item is being parsed: [2025-05-25 03:31:24] [Embedded] Audio stream: eng => eng [2025-05-25 03:31:24] [Embedded] Subtitle stream: eng => eng [2025-05-25 03:31:24] [Embedded] Audio stream: und => und [2025-05-25 03:31:24] [Embedded] Subtitle stream: el => gre 1
GrimReaper 4739 Posted May 25, 2025 Posted May 25, 2025 (edited) 11 minutes ago, akacharos said: no subtitle flag icon overlay anywhere. What am I missing here? You're using naming convention for audio languages while having audio icons disabled. If you want subtitle flags, you need to rename those files. From Github link: Quote Important: Icons must me named "eng.png" for audio tracks and "srt.eng.png" for subtitles, change eng with the language code you want like dan or jpn. Edit: @yocker, maybe the above should be denoted in plugin settings? Edited May 25, 2025 by GrimReaper Append 1
akacharos 31 Posted May 25, 2025 Posted May 25, 2025 ooops, I missed that bit. thanks so much @GrimReaper, I was going crazy with this, 1
bakes82 167 Posted May 25, 2025 Posted May 25, 2025 @yocker I was taking a quick pass at your code to make some tweaks and Im not sure what youre even doing... Why are you calling ffprobe, this is most like what most of youre issues are. All the information you are looking for exists in the database. I was confused as to why you cared what the file/sub extensions where in the settings as I was making them dynamic and regrouping them, and then I found this ffprobe stuff. Every baseItem has a GetMediaStreams options where you can determine if it has audio streams or subtitles, from there you can pull out the language, not sure why you would care about the file extension public List<EditorSelectOption> GetLanguageOptions(MediaStreamType type = MediaStreamType.Audio) { var result = new List<EditorSelectOption>(); var items = _libraryManager.GetItemList(new InternalItemsQuery { IsVirtualItem = false, Recursive = true, HasSubtitles = true, IncludeItemTypes = new[] { nameof(Episode), nameof(Movie) } }); var languages = items.SelectMany(e => e.GetMediaStreams().Where(x => x.Type == type).Select(x => x.Language)).Distinct().ToList(); foreach (var language in languages) { var option = new EditorSelectOption { Value = language, Name = language, IsEnabled = true }; result.Add(option); } return result.OrderBy(x => x.Name).ToList(); } from the rest api you can call the items endpoint and get results like this, which is what the libraymanager code above is doing { "Name": "RuPaul-A-Palooza!", "ServerId": "4ddd813384cf4b87bd7ea070dd03e2ca", "Id": "520021", "Container": "mkv", "MediaSources": [ { "Chapters": [], "Protocol": "File", "Id": "mediasource_520021", "Path": "/home/plex/media/TVShowsCurrent/RuPaul's Secret Celebrity Drag Race (2020)/Season 02/RuPaul's Secret Celebrity Drag Race (2020) - S02E06 - RuPaul-A-Palooza! - 371278 - x264 AAC2.0 SLAG WEBDL-1080p.mkv", "Type": "Default", "Container": "mkv", "Size": 1660689998, "Name": "RuPaul's Secret Celebrity Drag Race (2020) - S02E06 - RuPaul-A-Palooza! - 371278 - x264 AAC2.0 SLAG WEBDL-1080p", "IsRemote": false, "HasMixedProtocols": false, "RunTimeTicks": 25017320000, "SupportsTranscoding": true, "SupportsDirectStream": true, "SupportsDirectPlay": true, "IsInfiniteStream": false, "RequiresOpening": false, "RequiresClosing": false, "RequiresLooping": false, "SupportsProbing": false, "MediaStreams": [ { "Codec": "h264", "ColorTransfer": "bt709", "ColorPrimaries": "bt709", "ColorSpace": "bt709", "TimeBase": "1/1000", "VideoRange": "SDR", "DisplayTitle": "1080p H264", "NalLengthSize": "4", "IsInterlaced": false, "BitRate": 5310528, "BitDepth": 8, "RefFrames": 1, "IsDefault": true, "IsForced": false, "IsHearingImpaired": false, "Height": 1080, "Width": 1920, "AverageFrameRate": 29.97003, "RealFrameRate": 29.97003, "Profile": "High", "Type": "Video", "AspectRatio": "16:9", "Index": 0, "IsExternal": false, "IsTextSubtitleStream": false, "SupportsExternalStream": false, "Protocol": "File", "PixelFormat": "yuv420p", "Level": 40, "IsAnamorphic": false, "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0 }, { "Codec": "aac", "Language": "eng", "TimeBase": "1/1000", "DisplayTitle": "English AAC stereo (Default)", "DisplayLanguage": "English", "IsInterlaced": false, "ChannelLayout": "stereo", "BitRate": 192000, "Channels": 2, "SampleRate": 48000, "IsDefault": true, "IsForced": false, "IsHearingImpaired": false, "Profile": "LC", "Type": "Audio", "Index": 1, "IsExternal": false, "IsTextSubtitleStream": false, "SupportsExternalStream": false, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0 }, { "Codec": "subrip", "Language": "ger", "TimeBase": "1/1000", "Title": "Deutsch", "DisplayTitle": "German (SUBRIP)", "DisplayLanguage": "German", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 2, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "eng", "TimeBase": "1/1000", "Title": "English", "DisplayTitle": "English (SUBRIP)", "DisplayLanguage": "English", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 3, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "spa", "TimeBase": "1/1000", "Title": "Español", "DisplayTitle": "Spanish (SUBRIP)", "DisplayLanguage": "Spanish", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 4, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "fre", "TimeBase": "1/1000", "Title": "Français", "DisplayTitle": "French (SUBRIP)", "DisplayLanguage": "French", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 5, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ind", "TimeBase": "1/1000", "Title": "Indonesia", "DisplayTitle": "Indonesian (SUBRIP)", "DisplayLanguage": "Indonesian", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 6, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ita", "TimeBase": "1/1000", "Title": "Italiano", "DisplayTitle": "Italian (SUBRIP)", "DisplayLanguage": "Italian", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 7, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "dut", "TimeBase": "1/1000", "Title": "Nederlands", "DisplayTitle": "Dutch (SUBRIP)", "DisplayLanguage": "Dutch", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 8, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "por", "TimeBase": "1/1000", "Title": "Português", "DisplayTitle": "Portuguese (SUBRIP)", "DisplayLanguage": "Portuguese", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 9, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ara", "TimeBase": "1/1000", "Title": "العربية", "DisplayTitle": "Arabic (SUBRIP)", "DisplayLanguage": "Arabic", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 10, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "chi", "TimeBase": "1/1000", "Title": "中文", "DisplayTitle": "Chinese Simplified (SUBRIP)", "DisplayLanguage": "Chinese Simplified", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 11, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "jpn", "TimeBase": "1/1000", "Title": "日本語", "DisplayTitle": "Japanese (SUBRIP)", "DisplayLanguage": "Japanese", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 12, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "kor", "TimeBase": "1/1000", "Title": "한국어", "DisplayTitle": "Korean (SUBRIP)", "DisplayLanguage": "Korean", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 13, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" } ], "Formats": [], "Bitrate": 5310528, "RequiredHttpHeaders": {}, "AddApiKeyToDirectStreamUrl": false, "ReadAtNativeFramerate": false, "ItemId": "520021" } ], "RunTimeTicks": 25017320000, "Size": 1660689998, "Bitrate": 5310528, "IndexNumber": 6, "ParentIndexNumber": 2, "IsFolder": false, "Type": "Episode", "ParentLogoItemId": "395792", "ParentBackdropItemId": "395792", "ParentBackdropImageTags": [ "3d176bdab8ad47c88676035e1943c24f" ], "SeriesName": "RuPaul's Secret Celebrity Drag Race", "SeriesId": "395792", "SeasonId": "520018", "SeriesPrimaryImageTag": "c092746ee53f9e574ed8bf334501aad9", "SeasonName": "Season 2", "MediaStreams": [ { "Codec": "h264", "ColorTransfer": "bt709", "ColorPrimaries": "bt709", "ColorSpace": "bt709", "TimeBase": "1/1000", "VideoRange": "SDR", "DisplayTitle": "1080p H264", "NalLengthSize": "4", "IsInterlaced": false, "BitRate": 5310528, "BitDepth": 8, "RefFrames": 1, "IsDefault": true, "IsForced": false, "IsHearingImpaired": false, "Height": 1080, "Width": 1920, "AverageFrameRate": 29.97003, "RealFrameRate": 29.97003, "Profile": "High", "Type": "Video", "AspectRatio": "16:9", "Index": 0, "IsExternal": false, "IsTextSubtitleStream": false, "SupportsExternalStream": false, "Protocol": "File", "PixelFormat": "yuv420p", "Level": 40, "IsAnamorphic": false, "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0 }, { "Codec": "aac", "Language": "eng", "TimeBase": "1/1000", "DisplayTitle": "English AAC stereo (Default)", "DisplayLanguage": "English", "IsInterlaced": false, "ChannelLayout": "stereo", "BitRate": 192000, "Channels": 2, "SampleRate": 48000, "IsDefault": true, "IsForced": false, "IsHearingImpaired": false, "Profile": "LC", "Type": "Audio", "Index": 1, "IsExternal": false, "IsTextSubtitleStream": false, "SupportsExternalStream": false, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0 }, { "Codec": "subrip", "Language": "ger", "TimeBase": "1/1000", "Title": "Deutsch", "DisplayTitle": "German (SUBRIP)", "DisplayLanguage": "German", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 2, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "eng", "TimeBase": "1/1000", "Title": "English", "DisplayTitle": "English (SUBRIP)", "DisplayLanguage": "English", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 3, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "spa", "TimeBase": "1/1000", "Title": "Español", "DisplayTitle": "Spanish (SUBRIP)", "DisplayLanguage": "Spanish", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 4, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "fre", "TimeBase": "1/1000", "Title": "Français", "DisplayTitle": "French (SUBRIP)", "DisplayLanguage": "French", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 5, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ind", "TimeBase": "1/1000", "Title": "Indonesia", "DisplayTitle": "Indonesian (SUBRIP)", "DisplayLanguage": "Indonesian", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 6, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ita", "TimeBase": "1/1000", "Title": "Italiano", "DisplayTitle": "Italian (SUBRIP)", "DisplayLanguage": "Italian", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 7, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "dut", "TimeBase": "1/1000", "Title": "Nederlands", "DisplayTitle": "Dutch (SUBRIP)", "DisplayLanguage": "Dutch", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 8, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "por", "TimeBase": "1/1000", "Title": "Português", "DisplayTitle": "Portuguese (SUBRIP)", "DisplayLanguage": "Portuguese", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 9, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ara", "TimeBase": "1/1000", "Title": "العربية", "DisplayTitle": "Arabic (SUBRIP)", "DisplayLanguage": "Arabic", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 10, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "chi", "TimeBase": "1/1000", "Title": "中文", "DisplayTitle": "Chinese Simplified (SUBRIP)", "DisplayLanguage": "Chinese Simplified", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 11, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "jpn", "TimeBase": "1/1000", "Title": "日本語", "DisplayTitle": "Japanese (SUBRIP)", "DisplayLanguage": "Japanese", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 12, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "kor", "TimeBase": "1/1000", "Title": "한국어", "DisplayTitle": "Korean (SUBRIP)", "DisplayLanguage": "Korean", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 13, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" } ], "ImageTags": { "Primary": "b660265328f5bcd291a0cd393cfa58d2" }, "BackdropImageTags": [], "ParentLogoImageTag": "df2abf6a4cf32b008b4852dba98b6c91", "MediaType": "Video" },
yocker 1247 Posted May 25, 2025 Author Posted May 25, 2025 4 minutes ago, bakes82 said: @yocker I was taking a quick pass at your code to make some tweaks and Im not sure what youre even doing... Why are you calling ffprobe, this is most like what most of youre issues are. All the information you are looking for exists in the database. I was confused as to why you cared what the file/sub extensions where in the settings as I was making them dynamic and regrouping them, and then I found this ffprobe stuff. Every baseItem has a GetMediaStreams options where you can determine if it has audio streams or subtitles, from there you can pull out the language, not sure why you would care about the file extension public List<EditorSelectOption> GetLanguageOptions(MediaStreamType type = MediaStreamType.Audio) { var result = new List<EditorSelectOption>(); var items = _libraryManager.GetItemList(new InternalItemsQuery { IsVirtualItem = false, Recursive = true, HasSubtitles = true, IncludeItemTypes = new[] { nameof(Episode), nameof(Movie) } }); var languages = items.SelectMany(e => e.GetMediaStreams().Where(x => x.Type == type).Select(x => x.Language)).Distinct().ToList(); foreach (var language in languages) { var option = new EditorSelectOption { Value = language, Name = language, IsEnabled = true }; result.Add(option); } return result.OrderBy(x => x.Name).ToList(); } from the rest api you can call the items endpoint and get results like this, which is what the libraymanager code above is doing { "Name": "RuPaul-A-Palooza!", "ServerId": "4ddd813384cf4b87bd7ea070dd03e2ca", "Id": "520021", "Container": "mkv", "MediaSources": [ { "Chapters": [], "Protocol": "File", "Id": "mediasource_520021", "Path": "/home/plex/media/TVShowsCurrent/RuPaul's Secret Celebrity Drag Race (2020)/Season 02/RuPaul's Secret Celebrity Drag Race (2020) - S02E06 - RuPaul-A-Palooza! - 371278 - x264 AAC2.0 SLAG WEBDL-1080p.mkv", "Type": "Default", "Container": "mkv", "Size": 1660689998, "Name": "RuPaul's Secret Celebrity Drag Race (2020) - S02E06 - RuPaul-A-Palooza! - 371278 - x264 AAC2.0 SLAG WEBDL-1080p", "IsRemote": false, "HasMixedProtocols": false, "RunTimeTicks": 25017320000, "SupportsTranscoding": true, "SupportsDirectStream": true, "SupportsDirectPlay": true, "IsInfiniteStream": false, "RequiresOpening": false, "RequiresClosing": false, "RequiresLooping": false, "SupportsProbing": false, "MediaStreams": [ { "Codec": "h264", "ColorTransfer": "bt709", "ColorPrimaries": "bt709", "ColorSpace": "bt709", "TimeBase": "1/1000", "VideoRange": "SDR", "DisplayTitle": "1080p H264", "NalLengthSize": "4", "IsInterlaced": false, "BitRate": 5310528, "BitDepth": 8, "RefFrames": 1, "IsDefault": true, "IsForced": false, "IsHearingImpaired": false, "Height": 1080, "Width": 1920, "AverageFrameRate": 29.97003, "RealFrameRate": 29.97003, "Profile": "High", "Type": "Video", "AspectRatio": "16:9", "Index": 0, "IsExternal": false, "IsTextSubtitleStream": false, "SupportsExternalStream": false, "Protocol": "File", "PixelFormat": "yuv420p", "Level": 40, "IsAnamorphic": false, "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0 }, { "Codec": "aac", "Language": "eng", "TimeBase": "1/1000", "DisplayTitle": "English AAC stereo (Default)", "DisplayLanguage": "English", "IsInterlaced": false, "ChannelLayout": "stereo", "BitRate": 192000, "Channels": 2, "SampleRate": 48000, "IsDefault": true, "IsForced": false, "IsHearingImpaired": false, "Profile": "LC", "Type": "Audio", "Index": 1, "IsExternal": false, "IsTextSubtitleStream": false, "SupportsExternalStream": false, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0 }, { "Codec": "subrip", "Language": "ger", "TimeBase": "1/1000", "Title": "Deutsch", "DisplayTitle": "German (SUBRIP)", "DisplayLanguage": "German", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 2, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "eng", "TimeBase": "1/1000", "Title": "English", "DisplayTitle": "English (SUBRIP)", "DisplayLanguage": "English", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 3, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "spa", "TimeBase": "1/1000", "Title": "Español", "DisplayTitle": "Spanish (SUBRIP)", "DisplayLanguage": "Spanish", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 4, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "fre", "TimeBase": "1/1000", "Title": "Français", "DisplayTitle": "French (SUBRIP)", "DisplayLanguage": "French", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 5, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ind", "TimeBase": "1/1000", "Title": "Indonesia", "DisplayTitle": "Indonesian (SUBRIP)", "DisplayLanguage": "Indonesian", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 6, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ita", "TimeBase": "1/1000", "Title": "Italiano", "DisplayTitle": "Italian (SUBRIP)", "DisplayLanguage": "Italian", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 7, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "dut", "TimeBase": "1/1000", "Title": "Nederlands", "DisplayTitle": "Dutch (SUBRIP)", "DisplayLanguage": "Dutch", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 8, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "por", "TimeBase": "1/1000", "Title": "Português", "DisplayTitle": "Portuguese (SUBRIP)", "DisplayLanguage": "Portuguese", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 9, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ara", "TimeBase": "1/1000", "Title": "العربية", "DisplayTitle": "Arabic (SUBRIP)", "DisplayLanguage": "Arabic", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 10, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "chi", "TimeBase": "1/1000", "Title": "中文", "DisplayTitle": "Chinese Simplified (SUBRIP)", "DisplayLanguage": "Chinese Simplified", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 11, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "jpn", "TimeBase": "1/1000", "Title": "日本語", "DisplayTitle": "Japanese (SUBRIP)", "DisplayLanguage": "Japanese", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 12, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "kor", "TimeBase": "1/1000", "Title": "한국어", "DisplayTitle": "Korean (SUBRIP)", "DisplayLanguage": "Korean", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 13, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" } ], "Formats": [], "Bitrate": 5310528, "RequiredHttpHeaders": {}, "AddApiKeyToDirectStreamUrl": false, "ReadAtNativeFramerate": false, "ItemId": "520021" } ], "RunTimeTicks": 25017320000, "Size": 1660689998, "Bitrate": 5310528, "IndexNumber": 6, "ParentIndexNumber": 2, "IsFolder": false, "Type": "Episode", "ParentLogoItemId": "395792", "ParentBackdropItemId": "395792", "ParentBackdropImageTags": [ "3d176bdab8ad47c88676035e1943c24f" ], "SeriesName": "RuPaul's Secret Celebrity Drag Race", "SeriesId": "395792", "SeasonId": "520018", "SeriesPrimaryImageTag": "c092746ee53f9e574ed8bf334501aad9", "SeasonName": "Season 2", "MediaStreams": [ { "Codec": "h264", "ColorTransfer": "bt709", "ColorPrimaries": "bt709", "ColorSpace": "bt709", "TimeBase": "1/1000", "VideoRange": "SDR", "DisplayTitle": "1080p H264", "NalLengthSize": "4", "IsInterlaced": false, "BitRate": 5310528, "BitDepth": 8, "RefFrames": 1, "IsDefault": true, "IsForced": false, "IsHearingImpaired": false, "Height": 1080, "Width": 1920, "AverageFrameRate": 29.97003, "RealFrameRate": 29.97003, "Profile": "High", "Type": "Video", "AspectRatio": "16:9", "Index": 0, "IsExternal": false, "IsTextSubtitleStream": false, "SupportsExternalStream": false, "Protocol": "File", "PixelFormat": "yuv420p", "Level": 40, "IsAnamorphic": false, "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0 }, { "Codec": "aac", "Language": "eng", "TimeBase": "1/1000", "DisplayTitle": "English AAC stereo (Default)", "DisplayLanguage": "English", "IsInterlaced": false, "ChannelLayout": "stereo", "BitRate": 192000, "Channels": 2, "SampleRate": 48000, "IsDefault": true, "IsForced": false, "IsHearingImpaired": false, "Profile": "LC", "Type": "Audio", "Index": 1, "IsExternal": false, "IsTextSubtitleStream": false, "SupportsExternalStream": false, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0 }, { "Codec": "subrip", "Language": "ger", "TimeBase": "1/1000", "Title": "Deutsch", "DisplayTitle": "German (SUBRIP)", "DisplayLanguage": "German", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 2, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "eng", "TimeBase": "1/1000", "Title": "English", "DisplayTitle": "English (SUBRIP)", "DisplayLanguage": "English", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 3, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "spa", "TimeBase": "1/1000", "Title": "Español", "DisplayTitle": "Spanish (SUBRIP)", "DisplayLanguage": "Spanish", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 4, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "fre", "TimeBase": "1/1000", "Title": "Français", "DisplayTitle": "French (SUBRIP)", "DisplayLanguage": "French", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 5, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ind", "TimeBase": "1/1000", "Title": "Indonesia", "DisplayTitle": "Indonesian (SUBRIP)", "DisplayLanguage": "Indonesian", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 6, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ita", "TimeBase": "1/1000", "Title": "Italiano", "DisplayTitle": "Italian (SUBRIP)", "DisplayLanguage": "Italian", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 7, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "dut", "TimeBase": "1/1000", "Title": "Nederlands", "DisplayTitle": "Dutch (SUBRIP)", "DisplayLanguage": "Dutch", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 8, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "por", "TimeBase": "1/1000", "Title": "Português", "DisplayTitle": "Portuguese (SUBRIP)", "DisplayLanguage": "Portuguese", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 9, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "ara", "TimeBase": "1/1000", "Title": "العربية", "DisplayTitle": "Arabic (SUBRIP)", "DisplayLanguage": "Arabic", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 10, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "chi", "TimeBase": "1/1000", "Title": "中文", "DisplayTitle": "Chinese Simplified (SUBRIP)", "DisplayLanguage": "Chinese Simplified", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 11, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "jpn", "TimeBase": "1/1000", "Title": "日本語", "DisplayTitle": "Japanese (SUBRIP)", "DisplayLanguage": "Japanese", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 12, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" }, { "Codec": "subrip", "Language": "kor", "TimeBase": "1/1000", "Title": "한국어", "DisplayTitle": "Korean (SUBRIP)", "DisplayLanguage": "Korean", "IsInterlaced": false, "IsDefault": false, "IsForced": false, "IsHearingImpaired": false, "Type": "Subtitle", "Index": 13, "IsExternal": false, "IsTextSubtitleStream": true, "SupportsExternalStream": true, "Protocol": "File", "ExtendedVideoType": "None", "ExtendedVideoSubType": "None", "ExtendedVideoSubTypeDescription": "None", "AttachmentSize": 0, "SubtitleLocationType": "InternalStream" } ], "ImageTags": { "Primary": "b660265328f5bcd291a0cd393cfa58d2" }, "BackdropImageTags": [], "ParentLogoImageTag": "df2abf6a4cf32b008b4852dba98b6c91", "MediaType": "Video" }, Because i had problems with getting it to recognize when subtitles had chanced so as a temporary fix i used ffprobe. It had no noticeable performance impact so was of low priority to change while i got other things to work. It doesn't use that any more and solely relies on Emby. The file extensions setting for were just meant for my own testing purposes. It hasn't been part of my internal version for a while now. Something else though. I finally got it working as it should. I'm no people person and i usually don't like most contact but i could kiss you for this await baseItem.RefreshMetadata(metadataOptions, CancellationToken.None); //You can call this to pull fresh data but not replace images in the options _libraryManager.UpdateItem(baseItem, baseItem.Parent, ItemUpdateType.ImageUpdate); I might have been an idiot for missing that but as said i'm new at all this.
yocker 1247 Posted May 25, 2025 Author Posted May 25, 2025 (edited) Here is a version i would like people to test for a couple of days. It now reacts solely on Emby own internals workings, the posters should auto update now (thank you Bakes82) as they should and it should run smoother than before. The delay setting in the settings menus are for slower systems as to not bog them down when scanning files or refreshing metadata. Don't set it to low, 2-3 seconds should be fine. This setting is more or a "just in case", i will most likely remove it later when i'm absolutely sure that all systems can handle this. Lastly: BETA! BETA! BETA! BETA! BETA! BETA! The plugin should be 100% safe but it just haven't been tested yet and is fresh of the presses. Use at your own risk! Edited May 25, 2025 by yocker 1
bakes82 167 Posted May 25, 2025 Posted May 25, 2025 @yockerHere is an updated framework that I usually use for all my plugins, it uses more the the Emby UI tooling and not just the "easy" option you were. https://github.com/bakes82/EmbyIcons Look at EmbyIconsConfigPluginPageView as it will have all the logic you need, from there you should be able to back track, I also included some samples. I tend to keep everything in emby so I also put the sample for writing activities, and drop down examples, you should just need to update the "RunJob" section with your logic, all the drop downs if they are multi pick are CSV stored. 1
yocker 1247 Posted May 25, 2025 Author Posted May 25, 2025 Uploaded the wrong file by mistake before, it was an old middle of the road version. Very sorry about that. This is the one to test. EmbyIcons.dll
yocker 1247 Posted May 25, 2025 Author Posted May 25, 2025 46 minutes ago, bakes82 said: @yockerHere is an updated framework that I usually use for all my plugins, it uses more the the Emby UI tooling and not just the "easy" option you were. https://github.com/bakes82/EmbyIcons Look at EmbyIconsConfigPluginPageView as it will have all the logic you need, from there you should be able to back track, I also included some samples. I tend to keep everything in emby so I also put the sample for writing activities, and drop down examples, you should just need to update the "RunJob" section with your logic, all the drop downs if they are multi pick are CSV stored. Many thanks, i will look it up first thing a when i have a little time! Appreciate it!
keitaro26 22 Posted May 25, 2025 Posted May 25, 2025 3 minutes ago, yocker said: Uploaded the wrong file by mistake before, it was an old middle of the road version. Very sorry about that. This is the one to test. EmbyIcons.dll 1.54 MB · 0 downloads When I try to turn on the auto-refresh, I get this error: 1
yocker 1247 Posted May 25, 2025 Author Posted May 25, 2025 3 minutes ago, keitaro26 said: When I try to turn on the auto-refresh, I get this error: I thought something like this would happen for some. Just disable it for now. Emby has it's own filewatcher, i just wanted to see if i could do a better job than it and make sure icons got drawn all the time Thanks for testing!
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now