Jump to content

Automated Tagging


Steve86

Recommended Posts

3 minutes ago, bakes82 said:

The issue is a base item can have multi sources correct?  720p, 1080p?  So you need to get the info from the media source.

Looks like we're advising him to do the same thing.

Edited by roaku
Link to comment
Share on other sites

bakes82
Just now, roaku said:

Looks like we're advising him to do the same thing.

Sure lol, but he needs the context too, as it could impact how tagging works in general.  If tags are on the base item, how do you block just the 4k item or do you block them all?

Link to comment
Share on other sites

2 minutes ago, bakes82 said:

How does this plugin work when you have things merged:  🤐😬🤯

image.png.56ffbd72914b0d69f094284d74db14cc.png

BaseItem.GetMediaSources(...) gets you the MediaStream details for multi-versions.

 

Link to comment
Share on other sites

For the image enhancement plug in I'm working on, I match when *any* of the versions fulfill a rule.

A similar decision has to be made for the tagging. If any of the versions match, does the item get the tag?

  • Like 1
Link to comment
Share on other sites

bakes82
2 minutes ago, roaku said:

BaseItem.GetMediaSources(...) gets you the MediaStream details for multi-versions.

 

Yes I know it does, but when you applied a "4k" tag, does it apply to the base item of all the merge, or to the mediasourceitem :P

  • Like 1
Link to comment
Share on other sites

Just now, bakes82 said:

Yes I know it does, but when you applied a "4k" tag, does it apply to the base item of all the merge, or to the mediasourceitem :P

That's what sucks a bit about the multi-version set up...there's no quick access to 'sibling' items, right? There has to be additional querying if GetMediaSources has multiple entries *and* you find a match in one of the non-primary MediaSources.

Link to comment
Share on other sites

bakes82
Just now, roaku said:

That's what sucks a bit about the multi-version set up...there's no quick access to 'sibling' items, right? There has to be additional querying if GetMediaSources has multiple entries *and* you find a match in one of the non-primary MediaSources.

Right but the use case it, I want to block 4k tagged items, now where does the 4k tag live?  will it block the entire 1917 move because it has a source of 4k and a tag of 4k and a source of 1080p and a 1080p tag.  This is more my question.   Why Ive been asking all along, what is the real use case, as it might not be doable in all setups with a tag, especially if there is only 1 item and it has 10 tags now.  Hopefully that makes sense.

Link to comment
Share on other sites

1 minute ago, bakes82 said:

Right but the use case it, I want to block 4k tagged items, now where does the 4k tag live?  will it block the entire 1917 move because it has a source of 4k and a tag of 4k and a source of 1080p and a 1080p tag.  This is more my question.   Why Ive been asking all along, what is the real use case, as it might not be doable in all setups with a tag, especially if there is only 1 item and it has 10 tags now.  Hopefully that makes sense.


I think the simplest solution would be to get all the Items through the main endpoint instead of the User endpoint.
 

The main endpoint can return all the items, ignoring the multi-version groupings.

Link to comment
Share on other sites

This endpoint separates the items from their version groupings and lists them separately:

/emby/Items?api_key={apikey}&Recursive=true&IncludeItemTypes=Movie&Fields=Path,TagLines,Overview,PremiereDate,Genres,MediaStreams&SortBy=Name&SortOrder=Ascending

This endpoint returns only the primary items in a version group:

/emby/Users/{userid}/Items?api_key={apikey}&Recursive=true&IncludeItemTypes=Movie&Fields=Path,TagLines,Overview,PremiereDate,Genres,MediaStreams&SortBy=Name&SortOrder=Ascending

 

Edited by roaku
  • Like 1
Link to comment
Share on other sites

bakes82
3 minutes ago, roaku said:

This endpoint separates the items from their version groupings and lists them separately:


/emby/Items?api_key={apikey}&Recursive=true&IncludeItemTypes=Movie&Fields=Path,TagLines,Overview,PremiereDate,Genres,MediaStreams&SortBy=Name&SortOrder=Ascending

This endpoint only returns only the primary items in a version group:


/emby/Users/{userid}/Items?api_key={apikey}&Recursive=true&IncludeItemTypes=Movie&Fields=Path,TagLines,Overview,PremiereDate,Genres,MediaStreams&SortBy=Name&SortOrder=Ascending

 

Sidebar: you know of a way to make the primary always be like 4k if you have duplicates, now it seems random based on how you merged what with what

Link to comment
Share on other sites

3 minutes ago, bakes82 said:

Sidebar: you know of a way to make the primary always be like 4k if you have duplicates, now it seems random based on how you merged what with what

My understanding is that there is magic done by Emby to determine the 'best' candidate from the versions for the particular device/network conditions requesting the media and there's no way to just have it be alpha sorted or something similar.

I'd have to look up the forum posts where the devs talk about that.

I use multi-versions to store alternate cuts of movies dubbed/subtitled...I've been told we're not really supposed to do that...even though the Knowledge Base is where I learned how. :)

Edited by roaku
Link to comment
Share on other sites

bakes82
1 minute ago, roaku said:

My understanding is that there is magic done by Emby to determine the 'best' candidate from the versions for the particular device/network conditions requesting the media and there's no way to just have it be alpha sorted or something similar.

I'd have to look up the forum posts where the devs talk about that.

Right but the UI displays info from the 1st one in the drop down list :P  IDK how that list is populated, I would always want the highest bitrate first.  I know emby does other magic, but I turn that shit off, I set mine to max quality, otherwise if you have like a 4k and a 4kdv the dv is higher bitrate, sometimes emby will still pick 1080p because the speedtest was slow atm but the 4k dv 130gb file plays fine with no buffering

Link to comment
Share on other sites

1 minute ago, bakes82 said:

Right but the UI displays info from the 1st one in the drop down list :P  IDK how that list is populated, I would always want the highest bitrate first.  I know emby does other magic, but I turn that shit off, I set mine to max quality, otherwise if you have like a 4k and a 4kdv the dv is higher bitrate, sometimes emby will still pick 1080p because the speedtest was slow atm but the 4k dv 130gb file plays fine with no buffering

That part might be by file date created/modified or when the file was scanned into the db? I seem to remember being able to manipulate that a bit before I gave up trying to have control of it.

Link to comment
Share on other sites

So it sounds like I might have stumbled into this first ... uh .... 100th  issue.

Tagging the baseItem might not work for resolution because the baseItem contains many stream object.

tageditor12.png.f152b3b491b416211f9f9910e8bac93a.png

 

This shows a rule which say the user wants to target Resolution 1080p.

But, like you guys have mentioned the baseItem contains many streams. It could have 1080p and 2160p. This causes an issue for tagging the baseItem.

We can't tag a baseItem with two different rules, because (if the whole idea is to limit accessibility to an item) we would most likely, indirectly, tag both item streams.

 

Crap! we'll have to think this through a bit further. There is a 'gotcha' here which might make it harder to target and tag baseItems by Resolution.

 

 

Edited by chef
Link to comment
Share on other sites

4 minutes ago, chef said:

So it sounds like I might have stumbled into this first ... uh .... 100th  issue.

Tagging the baseItem might not work for resolution because the baseItem contains many stream object.

tageditor12.png.f152b3b491b416211f9f9910e8bac93a.png

 

This shows a rule which say the user wants to target Resolution 1080p.

In the schedule task I can do something like this:


                    foreach (var stream in item.GetMediaStreams())
                    {
                        if (stream.Width != null)
                        {
                            if (stream.Width == Convert.ToInt32(rule.Profile.Resolution.Replace("p", string.Empty)))
                            {

                            }
                        }
                    }

 

This would target the stream with a width of what ever the 'rule.Profile.Resoultion' is. 

Note: 1080p => 1080px width,  2160p => 2160px width (correct me if I'm wrong).

 

But, like you guys have mentioned the baseItem contains many streams. It could have 1080p and 2160p. This causes an issue for tagging the baseItem.

We can't tag a baseItem with two different rules, because (if the whole idea is to limit accessibility to an item) we would most likely, indirectly, tag both item streams.

 

Crap! we'll have to think this through a bit further. There is a 'gotcha' here which might make it harder to target and tag baseItems by Resolution.

Did you see this suggestion here to try getting the items ungrouped by version instead:

I think that this way, you'd be able to only ever look at the MediaStreams for that particular BaseItem (I'll look up the method/property for that) and manipulate the tags for that particular BaseItem.

 

 

  • Like 1
Link to comment
Share on other sites

I believe using BaseItem.GetMediaStreams() will return you only the MediaStreams for that particular Item.

  • Like 1
Link to comment
Share on other sites

32 minutes ago, roaku said:

This endpoint separates the items from their version groupings and lists them separately:


/emby/Items?api_key={apikey}&Recursive=true&IncludeItemTypes=Movie&Fields=Path,TagLines,Overview,PremiereDate,Genres,MediaStreams&SortBy=Name&SortOrder=Ascending

This endpoint returns only the primary items in a version group:


/emby/Users/{userid}/Items?api_key={apikey}&Recursive=true&IncludeItemTypes=Movie&Fields=Path,TagLines,Overview,PremiereDate,Genres,MediaStreams&SortBy=Name&SortOrder=Ascending

 

I the case of a 'user-less' request,  does each stream have an internalId (or Id in the REST case) attached to it.

I'll check it out. If it does, then this is what we' can do. We just have to make sure we can tag an item with an internalId.

Link to comment
Share on other sites

bakes82
4 minutes ago, chef said:

I the case of a 'user-less' request,  does each stream have an internalId (or Id in the REST case) attached to it.

I'll check it out. If it does, then this is what we' can do. We just have to make sure we can tag an item with an internalId.

do you have code someplace for me to view?

Link to comment
Share on other sites

1 minute ago, chef said:

I the case of a 'user-less' request,  does each stream have an internalId (or Id in the REST case) attached to it.

I'll check it out. If it does, then this is what we' can do. We just have to make sure we can tag an item with an internalId.

Going by memory, but I recall it having the right values for the 'hidden' items for both Id and InternalId

  • Thanks 1
Link to comment
Share on other sites

bakes82
Just now, roaku said:

Going by memory, but I recall it having the right values for the 'hidden' items for both Id and InternalId

the c# api this way does NOT have an id
 

var mediaSourceItem =
    sessionManagerSession.FullNowPlayingItem.GetMediaSources(false, false, new LibraryOptions())
        .SingleOrDefault(x =>
            string.Equals(x.Id, sessionManagerSession.PlayState.MediaSourceId,
                StringComparison.OrdinalIgnoreCase));

mediaSourceItem.MediaStreams.First().
Link to comment
Share on other sites

1 minute ago, bakes82 said:

the c# api this way does NOT have an id
 


var mediaSourceItem =
    sessionManagerSession.FullNowPlayingItem.GetMediaSources(false, false, new LibraryOptions())
        .SingleOrDefault(x =>
            string.Equals(x.Id, sessionManagerSession.PlayState.MediaSourceId,
                StringComparison.OrdinalIgnoreCase));

mediaSourceItem.MediaStreams.First().

We would want InternalId in this case.

Link to comment
Share on other sites

bakes82
Just now, roaku said:

We would want InternalId in this case.

Yeah I know, doesnt exist on the object returned

 

// Decompiled with JetBrains decompiler
// Type: MediaBrowser.Model.Entities.MediaStream
// Assembly: MediaBrowser.Model, Version=4.5.0.28, Culture=neutral, PublicKeyToken=null
// MVID: D6209AB7-0B07-4E22-B19D-786FB4321F01
// Assembly location: C:\Users\bradl\.nuget\packages\mediabrowser.common\4.5.0.28\lib\netstandard2.0\MediaBrowser.Model.dll

using MediaBrowser.Model.Dlna;
using MediaBrowser.Model.MediaInfo;
using System;

namespace MediaBrowser.Model.Entities
{
  public class MediaStream
  {
    private static ReadOnlyMemory<char>[] GraphicSubCodecNames = new ReadOnlyMemory<char>[3]
    {
      "DVB_TELETEXT".AsMemory(),
      "sub".AsMemory(),
      "dvb_subtitle".AsMemory()
    };
    private static ReadOnlyMemory<char>[] GraphicSubCodecPartialNames = new ReadOnlyMemory<char>[3]
    {
      "pgs".AsMemory(),
      "dvd".AsMemory(),
      "dvbsub".AsMemory()
    };
    private static ReadOnlyMemory<char> AssCodecName = "ass".AsMemory();
    private static ReadOnlyMemory<char> SsaCodecName = "ssa".AsMemory();

    public string Codec { get; set; }

    public string CodecTag { get; set; }

    public string Language { get; set; }

    public string ColorTransfer { get; set; }

    public string ColorPrimaries { get; set; }

    public string ColorSpace { get; set; }

    public string Comment { get; set; }

    public long? StreamStartTimeTicks { get; set; }

    public string TimeBase { get; set; }

    public string CodecTimeBase { get; set; }

    public string Title { get; set; }

    public string Extradata { get; set; }

    public string VideoRange
    {
      get
      {
        if (this.Type != MediaStreamType.Video)
          return (string) null;
        string colorTransfer = this.ColorTransfer;
        return !string.IsNullOrEmpty(colorTransfer) && (string.Equals(colorTransfer, "smpte2084", StringComparison.OrdinalIgnoreCase) || string.Equals(colorTransfer, "arib-std-b67", StringComparison.OrdinalIgnoreCase)) ? "HDR" : "SDR";
      }
    }

    public string DisplayTitle { get; set; }

    public string DisplayLanguage { get; set; }

    public string NalLengthSize { get; set; }

    public bool IsInterlaced { get; set; }

    public bool? IsAVC { get; set; }

    public string ChannelLayout { get; set; }

    public int? BitRate { get; set; }

    public int? BitDepth { get; set; }

    public int? RefFrames { get; set; }

    [Obsolete("Currently this property doesn't have any write usage.'")]
    public int? PacketLength { get; set; }

    public int? Channels { get; set; }

    public int? SampleRate { get; set; }

    public bool IsDefault { get; set; }

    public bool IsForced { get; set; }

    public int? Height { get; set; }

    public int? Width { get; set; }

    public float? AverageFrameRate { get; set; }

    public float? RealFrameRate { get; set; }

    public string Profile { get; set; }

    public MediaStreamType Type { get; set; }

    public string AspectRatio { get; set; }

    public int Index { get; set; }

    public int? Score { get; set; }

    public bool IsExternal { get; set; }

    public SubtitleDeliveryMethod? DeliveryMethod { get; set; }

    public string DeliveryUrl { get; set; }

    public bool? IsExternalUrl { get; set; }

    public bool IsTextSubtitleStream
    {
      get
      {
        if (this.Type != MediaStreamType.Subtitle)
          return false;
        string codec = this.Codec;
        return (!string.IsNullOrEmpty(codec) || this.IsExternal) && MediaStream.IsTextFormat(codec.AsSpan());
      }
    }

    public static bool IsTextFormat(ReadOnlySpan<char> codec)
    {
      if (codec.IsEmpty)
        return true;
      foreach (ReadOnlyMemory<char> graphicSubCodecName in MediaStream.GraphicSubCodecNames)
      {
        if (MemoryExtensions.Equals(graphicSubCodecName.Span, codec, StringComparison.OrdinalIgnoreCase))
          return false;
      }
      foreach (ReadOnlyMemory<char> codecPartialName in MediaStream.GraphicSubCodecPartialNames)
      {
        if (codec.Contains(codecPartialName.Span, StringComparison.OrdinalIgnoreCase))
          return false;
      }
      return true;
    }

    public bool SupportsSubtitleConversionTo(ReadOnlySpan<char> toCodec)
    {
      if (!this.IsTextSubtitleStream)
        return false;
      ReadOnlySpan<char> span1 = MediaStream.AssCodecName.Span;
      ReadOnlySpan<char> span2 = MediaStream.SsaCodecName.Span;
      if (MemoryExtensions.Equals(span1, toCodec, StringComparison.OrdinalIgnoreCase) || MemoryExtensions.Equals(span2, toCodec, StringComparison.OrdinalIgnoreCase))
        return false;
      ReadOnlySpan<char> other = this.Codec.AsSpan();
      return !MemoryExtensions.Equals(span1, other, StringComparison.OrdinalIgnoreCase) && !MemoryExtensions.Equals(span2, other, StringComparison.OrdinalIgnoreCase);
    }

    public bool SupportsExternalStream { get; set; }

    public string Path { get; set; }

    public MediaProtocol Protocol { get; set; }

    public string PixelFormat { get; set; }

    public double? Level { get; set; }

    public bool? IsAnamorphic { get; set; }

    public override string ToString() => string.Format("{0}: {1} {2}", (object) this.Type, (object) this.Codec, (object) this.DisplayTitle);
  }
}

 

  • Thanks 1
Link to comment
Share on other sites

The value we need is exposed as 'Id' through the rest api:

/emby/Items?api_key={apikey}&Recursive=true&IncludeItemTypes=Movie&Fields=Path,TagLines,Overview,PremiereDate,Genres,MediaStreams&SortBy=Name&SortOrder=Ascending
[
  {
    "Name": "Airplane!",
    "ServerId": "84be18a2e4db4328ab7b6fe164491562",
    "Id": "1402",
    "Container": "mkv",
    "PremiereDate": "1980-07-01T06:00:00.0000000+00:00",
    ...
  },
  {
    "Name": "Airplane!",
    "ServerId": "84be18a2e4db4328ab7b6fe164491562",
    "Id": "1403",
    "Container": "mkv",
    "PremiereDate": "1980-07-02T05:00:00.0000000+00:00",
    ...
  }
]

 

Link to comment
Share on other sites

Then resolution is a problem.  Was that in the OP request? Limiting access to 4k streams through tagging? 😬

Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...