h.buckle 11 Posted March 27, 2023 Share Posted March 27, 2023 After reading about custom metadata providers here I wanted to add a small one to do a bit of post-processing after the remote providers have run. I've added this class using System.Threading; using System.Threading.Tasks; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Library; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Configuration; using MediaBrowser.Model.Logging; using MediaBrowser.Model.Serialization; namespace JsonMetadata.Providers { public sealed class PersonNormalisationProvider : ICustomMetadataProvider<Person>, IMetadataProvider<Person>, ICustomMetadataProvider, IMetadataProvider, IForcedProvider { private readonly ILogger _logger; private readonly IJsonSerializer _jsonSerializer; public PersonNormalisationProvider(ILogger logger, IJsonSerializer jsonSerializer) { _logger = logger; _jsonSerializer = jsonSerializer; } public string Name => "PersonNormalisationProvider"; public Task<ItemUpdateType> FetchAsync(MetadataResult<Person> metadataResult, MetadataRefreshOptions options, LibraryOptions libraryOptions, CancellationToken cancellationToken) { if (metadataResult.HasMetadata) { Person item = metadataResult.Item; // do things return Task.FromResult(ItemUpdateType.MetadataEdit); } else { return Task.FromResult(ItemUpdateType.None); } } } } However the metadataResult object seems to always be empty - it always comes out like this if I log it using jsonSerializer { "Item": { "ImportedCollections": null }, "BaseItem": { "ImportedCollections": null }, "Images": [], "SearchImageUrl": null, "UserDataList": null, "People": null, "ListItems": null, "MediaStreams": null, "Chapters": null, "HasMetadata": false, "ResultLanguage": "en", "Provider": null, "QueriedById": false } Any idea what I need to do to get the actual item passed in? Link to comment Share on other sites More sharing options...
h.buckle 11 Posted March 27, 2023 Author Share Posted March 27, 2023 Server version is 4.8.0.26 and I'm using mediabrowser.server.core version 4.8.0.24-beta Link to comment Share on other sites More sharing options...
softworkz 3338 Posted March 27, 2023 Share Posted March 27, 2023 Set up debugging as explained here: https://betadev.emby.media/doc/plugins/dev/index.html#debugging The metadata result properties are not populated because custom metadata providers are run after the remote provider metadata has already been applied to the items. Yet, the .Item property is not null - it has at least serialized the ImportedCollections property, but all other properties are disabled for serialization, that's why you don't see them when serializing. Link to comment Share on other sites More sharing options...
h.buckle 11 Posted March 27, 2023 Author Share Posted March 27, 2023 OK I think that makes sense now - I was thinking the complete item would be passed in. Is the correct workflow then to get the complete item with LibraryManager and then update the MetadataResult with any changed properties? Link to comment Share on other sites More sharing options...
softworkz 3338 Posted March 27, 2023 Share Posted March 27, 2023 1 minute ago, h.buckle said: OK I think that makes sense now - I was thinking the complete item would be passed in 1. No 2. Yes, the complete item is passed in 2 minutes ago, h.buckle said: Is the correct workflow then to get the complete item with LibraryManager and then update the MetadataResult with any changed properties? No. The workflow is correct exactly like in your code snippet. Link to comment Share on other sites More sharing options...
softworkz 3338 Posted March 27, 2023 Share Posted March 27, 2023 1 minute ago, softworkz said: the complete item is passed in And it's not yet saved at this time. Link to comment Share on other sites More sharing options...
h.buckle 11 Posted March 27, 2023 Author Share Posted March 27, 2023 Mmmm, that doesn't seem to match what I'm seeing. If I change to this public Task<ItemUpdateType> FetchAsync(MetadataResult<Person> metadataResult, MetadataRefreshOptions options, LibraryOptions libraryOptions, CancellationToken cancellationToken) { Person item = metadataResult.Item; _logger.Log(LogSeverity.Info, $"JsonMetadata: {item.Overview}"); return Task.FromResult(ItemUpdateType.MetadataEdit); } This is what I see in the log Quote 2023-03-27 09:57:57.875 Debug SqliteItemRepository: GetitemById Person 1377783 Taraji P. Henson 2023-03-27 09:57:57.896 Debug DataExplorerService: Running TheMovieDb (MovieDbPersonProvider) for Taraji P. Henson 2023-03-27 09:57:57.926 Debug DataExplorerService: >>>>>> TheMovieDb returned metadata for Taraji P. Henson 2023-03-27 09:57:57.926 Debug DataExplorerService: Running PersonNormalisationProvider (PersonNormalisationProvider) for Taraji P. Henson 2023-03-27 09:57:57.927 Info App: JsonMetadata: 2023-03-27 09:57:57.928 Debug DataExplorerService: >>>>>> PersonNormalisationProvider returned metadata for Taraji P. Henson The Overview property should be present, as it is populated from the TmdbProvider, which runs previously? Link to comment Share on other sites More sharing options...
softworkz 3338 Posted March 27, 2023 Share Posted March 27, 2023 The Data Explorer Service is not normal Emby operation. It works differently and runs all providers in an isolated way. Not even the remote metadata providers are seeing the results from other remote providers. This is for being able to clearly show which data is coming from which provider. Also it never saves any data to the items. You need to use the context menu on the item and choose "Refresh Metadata". Link to comment Share on other sites More sharing options...
h.buckle 11 Posted March 28, 2023 Author Share Posted March 28, 2023 Ahh you are right, I was using the data explorer as a quicker way to test without refreshing all the time. I guess it means data explorer can't really test custom providers then, if they don't get the full item passed in that way? Link to comment Share on other sites More sharing options...
softworkz 3338 Posted March 28, 2023 Share Posted March 28, 2023 38 minutes ago, h.buckle said: Ahh you are right, I was using the data explorer as a quicker way to test without refreshing all the time. I guess it means data explorer can't really test custom providers then, if they don't get the full item passed in that way? Metadata providers are actually meant to provide metadata rather than to modify existing data and data explorer can really test such providers. As said above, data explorer executes every provider in an isolated way - as if it was the only available provider. For custom metadata providers, it creates an empty item object with nothing else but the path of the item. Example: The ffprobe provider is a custom metadata provider. After executing it, the DataExplorer is able to show you in the UI exactly the data that came from the ffprobe provider (because the item it supplies didn't have any other data before). Custom providers which do not provide but modify existing data are an accepted edge case. But if such provider does not add any data but just modifies existing data, the Data Explorer will always show that provider with all data empty - because it doesn't actually "provide" any data. Data Explorer can be useful for testing providers as it eliminates the influence of other providers - I've used that myself. But it can't and shouldn't be used a replacement for testing behavior in the actual context of provider execution. And in your specific case (modifying existing data), it's not useful at all. Link to comment Share on other sites More sharing options...
softworkz 3338 Posted March 28, 2023 Share Posted March 28, 2023 Another note: As you are intending to modify existing data, you should make sure that your provider gets invoked as last. To do that you should implement the IHasOrder interface (https://dev.emby.media/reference/pluginapi/MediaBrowser.Controller.Providers.IHasOrder.html?q=IHasOrder) and return a high number (e.g. 99). Link to comment Share on other sites More sharing options...
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