Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Respect transcoding user policy #1383

Closed
wants to merge 4 commits into from

Conversation

cewert
Copy link
Member

@cewert cewert commented Sep 19, 2023

These settings are accessed from the admin dashboard in the web client. Select "Users" then select a user to see the options.

user-policy

Changes

  • Remove audio entries in the transcodingprofiles array if audio transcoding is disabled
  • Remove video entries in the transcodingprofiles array if video transcoding is disabled

Issues

Fixes #1382

@cewert cewert changed the title Empty Transcoding profile if user policy says transcoding is disabled Respect transcoding user policy Sep 19, 2023
@cewert
Copy link
Member Author

cewert commented Sep 20, 2023

Tested this and it works fine. Removing draft tag

@cewert cewert marked this pull request as ready for review September 20, 2023 00:27
@cewert cewert requested a review from a team as a code owner September 20, 2023 00:27
@wwall3r
Copy link

wwall3r commented Sep 20, 2023

I tested this last night and it still selected a default audio track which was unsupported by the wireless headphones (DTS rather than AAC).

@cewert
Copy link
Member Author

cewert commented Sep 20, 2023

@wwall3r the device profile gets sent to the server at startup and when the hardware config changes(at least it's supposed to. you can search your logs for event.audioCodecCapabilityChanged to see if the app is detecting your change in hardware).

When exactly are you connecting your wireless headphones? For example, if you start the movie and then connect the headphones it's not going to work as the profile was built using your device and there isn't time to build a new device profile and send it to the server. Can you try connecting your headphones ASAP, before you start the jellyfin app if possible, and see if that fixes it?

@wwall3r
Copy link

wwall3r commented Sep 20, 2023

The headphones were connected before starting Jellyfin. I can try it again with the logging connected later.

@cewert
Copy link
Member Author

cewert commented Sep 20, 2023

@wwall3r interesting thanks. I don't understand how your code change fixed the issue then. You are using the same function we use to build the device profile - CanDecodeAudio(). I don't understand how it is reporting support for DTS at startup but then with your code change it's reporting it can't decode DTS and therefore picks another audio track.

Sounds good, thank you. Please post the entire log if you can - copy/paste the "Output" tab if using VSCode to deploy

@wwall3r
Copy link

wwall3r commented Sep 21, 2023

I turned on the Jellyfin Server debug logs, and I think the issue is that the Roku is only reporting 2 channel support, despite the fact that it can downmix 5.1 itself.

------ Running dev 'Jellyfin' main ------
09-21 00:36:45.655 [scrpt.ctx.run.enter] UI: Entering 'Jellyfin', id 'dev'
Previous server connection saved to registry
Active user found in registry
Auth token found in registry
Attempting to use API with auth token
Success! Auth token is still valid
m.global.session.user.settings =                <Component: roAssociativeArray> =
{
    content.candelete: true
    itemgrid.gridTitles: "showonhover"
    itemgrid.movieDefaultView: "movies"
    itemgrid.reset: true
    itemgrid.showItemCount: false
    livetv.canrecord: true
    load.allowwhatsnew: true
    playback.av1: true
    playback.bitrate.limit: "0"
    playback.bitrate.maxlimited: false
    playback.cinemamode: false
    playback.compatibility.disablehevc: false
    playback.forceDTS: true
    playback.mpeg2: false
    playback.mpeg4: true
    playback.nextupbuttonseconds: "30"
    playback.resolution.max: "auto"
    playback.resolution.mode: "transcoding"
    playback.subs.custom: false
    playback.subs.onlytext: false
    playback.tryDirect.h264ProfileLevel: true
    playback.tryDirect.hevcProfileLevel: true
    ui.design.hideclock: false
    ui.details.hidetagline: false
    ui.details.maxdaysnextup: "365"
    ui.home.splashBackground: false
    ui.tvshows.blurunwatched: false
    ui.tvshows.disableCommunityRating: false
    ui.tvshows.disableUnwatchedEpisodeCount: false
    ui.tvshows.goStraightToEpisodeListing: false
}
profile =       <Component: roAssociativeArray> =
{
    AppStoreUrl: "https://channelstore.roku.com/details/cc5e559d08d9ec87c5f30dcebdeebc12/jellyfin"
    DeviceProfile: <Component: roAssociativeArray>
    PlayableMediaTypes: <Component: roArray>
    SupportedCommands: <Component: roArray>
    SupportsContentUploading: false
    SupportsMediaControl: false
    SupportsPersistentIdentifier: false
    SupportsSync: false
}
profile.DeviceProfile =         <Component: roAssociativeArray> =
{
    CodecProfiles: <Component: roArray>
    ContainerProfiles: <Component: roArray>
    DirectPlayProfiles: <Component: roArray>
    FriendlyName: "Roku Ultra"
    Id: "cb62dcc5-0b07-54b7-af12-0961e8b2784b"
    Identification: <Component: roAssociativeArray>
    Manufacturer: "Roku"
    MaxStaticBitrate: 100000000
    MaxStreamingBitrate: 120000000
    ModelDescription: "Type: STB"
    ModelName: "Roku Ultra"
    ModelNumber: "4800X"
    MusicStreamingTranscodingBitrate: 192000
    Name: "Official Roku Client"
    SerialNumber: ""
    SubtitleProfiles: <Component: roArray>
    transcodingprofiles: <Component: roArray>
}
profile.DeviceProfile.CodecProfiles =
<Component: roAssociativeArray> =
{
    Conditions: <Component: roArray>
    Type: "VideoAudio"
}
<Component: roAssociativeArray> =
{
    Condition: "LessThanEqual"
    IsRequired: false
    Property: "AudioChannels"
    Value: "2"
}
<Component: roAssociativeArray> =
{
    Codec: "h264"
    Conditions: <Component: roArray>
    Type: "Video"
}
<Component: roAssociativeArray> =
{
    Condition: "NotEquals"
    IsRequired: false
    Property: "IsAnamorphic"
    Value: "true"
}
<Component: roAssociativeArray> =
{
    Condition: "EqualsAny"
    IsRequired: false
    Property: "VideoProfile"
    Value: "high|main"
}
<Component: roAssociativeArray> =
{
    Condition: "EqualsAny"
    IsRequired: false
    Property: "VideoRangeType"
    Value: "SDR"
}
<Component: roAssociativeArray> =
{
    Codec: "hevc"
    Conditions: <Component: roArray>
    Type: "Video"
}
<Component: roAssociativeArray> =
{
    Condition: "NotEquals"
    IsRequired: false
    Property: "IsAnamorphic"
    Value: "true"
}
<Component: roAssociativeArray> =
{
    Condition: "EqualsAny"
    IsRequired: false
    Property: "VideoProfile"
    Value: "main|main 10"
}
<Component: roAssociativeArray> =
{
    Condition: "EqualsAny"
    IsRequired: false
    Property: "VideoRangeType"
    Value: "SDR"
}
profile.DeviceProfile.ContainerProfiles =       <Component: roArray> =
[
]
profile.DeviceProfile.DirectPlayProfiles =
<Component: roAssociativeArray> =
{
    AudioCodec: "mp3,mp2,pcm,ac3,flac,aac,eac3"
    Container: "ts"
    Type: "Video"
    VideoCodec: "h264,mpeg4 avc,hevc,h265,mpeg4"
}
<Component: roAssociativeArray> =
{
    AudioCodec: "mp3,mp2,pcm,ac3,flac,alac,aac,opus,vorbis,eac3"
    Container: "mkv,webm"
    Type: "Video"
    VideoCodec: "h264,mpeg4 avc,vp8,vp9,hevc,h265,mpeg4"
}
<Component: roAssociativeArray> =
{
    AudioCodec: "ac3,aac,eac3"
    Container: "ism"
    Type: "Video"
    VideoCodec: "h264,mpeg4 avc,hevc,h265,mpeg4"
}
<Component: roAssociativeArray> =
{
    AudioCodec: "mp3,mp2,ac3,alac,aac,eac3"
    Container: "mp4,mov,m4v"
    Type: "Video"
    VideoCodec: "h264,mpeg4 avc,hevc,h265,mpeg4"
}
<Component: roAssociativeArray> =
{
    AudioCodec: "mp3,mp2,ac3,aac,eac3"
    Container: "hls"
    Type: "Video"
    VideoCodec: "h264,mpeg4 avc,hevc,h265,mpeg4"
}
<Component: roAssociativeArray> =
{
    AudioCodec: "aac"
    Container: "dash"
    Type: "Video"
    VideoCodec: "h264,mpeg4 avc,hevc,h265,mpeg4"
}
<Component: roAssociativeArray> =
{
    Container: "mp3,mp2,pcm,ac3,flac,alac,aac,opus,vorbis,eac3"
    Type: "Audio"
}
profile.DeviceProfile.SubtitleProfiles =
<Component: roAssociativeArray> =
{
    Format: "vtt"
    Method: "External"
}
<Component: roAssociativeArray> =
{
    Format: "srt"
    Method: "External"
}
<Component: roAssociativeArray> =
{
    Format: "ttml"
    Method: "External"
}
<Component: roAssociativeArray> =
{
    Format: "sub"
    Method: "External"
}
profile.DeviceProfile.TranscodingProfiles =
profile.PlayableMediaTypes =    <Component: roArray> =
[
    "Audio"
    "Video"
    "Photo"
]
profile.SupportedCommands =     <Component: roArray> =
[
]
event.Mode =    Instant replay
event.Mute =    false
09-21 00:36:49.026 [beacon.signal] |AppLaunchComplete ---------> Pending Render Pass
09-21 00:36:49.031 [beacon.signal] |AppLaunchComplete ---------> Duration(4287 ms)
09-21 00:37:22.384 [beacon.signal] |VODStartInitiate ----------> TimeBase(36009 ms)
09-21 00:37:22.384 [beacon.signal] |VODStartComplete ----------> Duration(1591 ms)
09-21 00:37:39.491 [beacon.signal] |VODStartInitiate ----------> TimeBase(53717 ms)
09-21 00:37:39.491 [beacon.signal] |VODStartComplete ----------> Duration(1016 ms)
09-21 00:50:34.698 [beacon.signal] |VODStartInitiate ----------> TimeBase(828960 ms)
09-21 00:50:34.699 [beacon.signal] |VODStartComplete ----------> Duration(980 ms)
09-21 00:52:35.072 [beacon.signal] |AppExitInitiate -----------> TimeBase(950328 ms)

@Shadowghost
Copy link
Contributor

Shouldn't this be solely handled by server?

@cewert
Copy link
Member Author

cewert commented Sep 21, 2023

@Shadowghost I'm not sure what the servers role is in all this. All I know is without this PR, our client will try to transcode files as needed and will completely ignore what the user policy says.

@Shadowghost
Copy link
Contributor

It should work like this: client builds profile based on what it can playback (codecs, audio channels, HDR, etc.) and sends it to server with the play request. Server then selects the best transcoding choice to match the supported client capabilities or direct plays if all codecs are compatible

@wwall3r
Copy link

wwall3r commented Sep 21, 2023

Screenshot 2023-09-21 at 8 43 41 AM

As noted in the discussion and the PR comment, Jellyfin allows for users to have varying permissions regarding transcoding. In this case, none of my users are allowed transcoding due to limited server hardware.

Therefore direct play is the only thing that works. The problem is that the correct audio track is not being chosen by the Roku client when an item is selected. If I manually choose "Options > Audio > AAC track," it works fine. The goal here is to have the client choose that track automatically based on the current hardware configuration.

Edit:
ffprobe of example file

Input #0, matroska,webm, from '/file.mkv':
  Metadata:
    title           : g33k
    ENCODER         : Lavf59.27.100
  Duration: 02:49:03.96, start: 0.000000, bitrate: 11776 kb/s
  Stream #0:0(eng): Video: h264, yuv420p(tv, bt709, progressive), 1920x1080, SAR 1:1 DAR 16:9, 23.98 fps, 23.98 tbr, 1k tbn (default)
    Metadata:
      DURATION        : 02:49:03.945000000
  Stream #0:1(eng): Audio: dts, 48000 Hz, 5.1(side), fltp, 1536 kb/s (default)
    Metadata:
      title           : DTS
      DURATION        : 02:49:03.955000000
  Stream #0:2(eng): Audio: aac, 48000 Hz, 6 channels, fltp (default)
    Metadata:
      title           : AAC
      ENCODER         : Lavc59.37.100 aac
      DURATION        : 02:49:03.956000000

One DTS track for when it is plugged directly into the receiver (works). One AAC track for when wireless headphones are connected (works, but is not chosen automatically by the client in that hardware configuration).

@Shadowghost
Copy link
Contributor

That does make sense. I guess my train of thoughts went in the totally wrong direction 😅

@sevenrats
Copy link
Member

is this how any other clients handle it? I'm not against the code is very clean im just confused why we need to do this.

@wwall3r
Copy link

wwall3r commented Sep 23, 2023

Both the Web and Android clients had similar issues on my mobile phone. However, that is due to a separate issue where the hardware does not report native mkv container support (Pixel 4a). VLC plays the files just fine with full acceleration enabled. However, that is not the problem being discussed in this PR, since the Roku Ultra has native support for the files in question.

If the clients do not intend to support this feature from the server, I can enable transcoding. However, I'm pretty much screwed any time it attempts to transcode a video stream due to the low-end hardware on which my server is running. Audio and containers transcode well.

source/utils/deviceCapabilities.brs Outdated Show resolved Hide resolved
source/utils/deviceCapabilities.brs Outdated Show resolved Hide resolved
source/utils/deviceCapabilities.brs Outdated Show resolved Hide resolved
source/utils/deviceCapabilities.brs Outdated Show resolved Hide resolved
source/utils/deviceCapabilities.brs Outdated Show resolved Hide resolved
@cewert cewert requested a review from 1hitsong September 25, 2023 00:28
@1hitsong
Copy link
Member

1hitsong commented Oct 15, 2023

Does the audio transcode setting only affect audio file playback and the video transcode setting only affect video playback? Or does the audio setting impact the audio in video files?

The reason I ask, enabling/disabling audio transcoding appears to work on audio files already in the prod client.

@cewert
Copy link
Member Author

cewert commented Oct 15, 2023

@1hitsong great question and good catch. I don't know the answer.

We may not even need this PR because I was told that the server will enforce this in v10.9.0 but I never spun up the v10.9.0 beta server to test.

@cewert cewert marked this pull request as draft October 16, 2023 15:18
@jellyfin-bot jellyfin-bot added the merge-conflict This PR has a merge conflict label Nov 4, 2023
@jellyfin-bot
Copy link
Contributor

This pull request has merge conflicts. Please resolve the conflicts so the PR can be reviewed. Thanks!

@jellyfin-bot
Copy link
Contributor

This pull request has merge conflicts. Please resolve the conflicts so the PR can be reviewed. Thanks!

@jellyfin-bot
Copy link
Contributor

This pull request has merge conflicts. Please resolve the conflicts so the PR can be reviewed. Thanks!

@jellyfin-bot jellyfin-bot added merge-conflict This PR has a merge conflict and removed merge-conflict This PR has a merge conflict labels Nov 11, 2023
@jellyfin-bot
Copy link
Contributor

This pull request has merge conflicts. Please resolve the conflicts so the PR can be reviewed. Thanks!

@cewert cewert changed the base branch from unstable to master December 14, 2023 15:07
@cewert cewert closed this Jan 13, 2024
@cewert cewert deleted the disable-transcoding branch January 14, 2024 01:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merge-conflict This PR has a merge conflict
Projects
Development

Successfully merging this pull request may close these issues.

6 participants