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

视频播放分辨率不符合预期 #30

Closed
amtoaer opened this issue Apr 10, 2024 · 16 comments
Closed

视频播放分辨率不符合预期 #30

amtoaer opened this issue Apr 10, 2024 · 16 comments

Comments

@amtoaer
Copy link
Contributor

amtoaer commented Apr 10, 2024

尝试点开一个 4k 电影播放,发现 mpv 中视频分辨率相当低,但 emby 控制台显示的是直接播放。

之前没有用过 mpv,不清楚是 mpv 配置问题还是项目问题,提个 issue 寻求帮助(

image
image

@tsukinaha
Copy link
Owner

@amtoaer 怎么拿到的是 m3u8 ,看一眼媒体信息?

@Kosette
Copy link
Collaborator

Kosette commented Apr 10, 2024

看一下emby server是否开启了transcoding,如果强制关闭还有没有这样的情况。

@amtoaer
Copy link
Contributor Author

amtoaer commented Apr 10, 2024

好的,我的机器在公司,明天看一下,感谢

@ZBound
Copy link
Contributor

ZBound commented Apr 11, 2024

转码需要在单个用户配置中关闭,需要注意一下

@amtoaer
Copy link
Contributor Author

amtoaer commented Apr 11, 2024

刚刚试过了,在单个用户配置内关闭转码可以 work。
不过我在 mac 上使用 infuse 可以在不调整用户配置的前提下做到直接播放不转码,因此这可能是一个客户端能够设置的属性?
我看到视频播放参数中有“TranscodeReasons=ContainerBitrateExceedsLimit”字样,在 jellyfin 社区发现了一个相关问题,回复指出用户后台将比特率配置为“自动”时在Android TV 上可能会错误地将比特率设置的非常低(想了想感觉也可能是我公网访问 NAS 连接状态不太好),可以通过手动切换比特率实现。

@tsukinaha
Copy link
Owner

@amtoaer 怀疑可能是请求体中的 MaxStaticBitrate:140000000 MaxStreamingBitrate:140000000 导致了转码
尝试一下把这几项调高看看有用吗

@amtoaer
Copy link
Contributor Author

amtoaer commented Apr 11, 2024

刚刚尝试提高到了一个很高的值,还是不行,不过确实感觉是这个参数的影响。我看到里面有一个 DirectPlayProfiles,里面没有包含 h265,所以有点怀疑是这个导致 hevc 视频走到转码了,不过要先工作,没时间调了(
下面是这个电影的参数:
image
等我有时间可以看看接口文档尝试修一下,或者也可以给你开一个 emby 账号你来试试(

@Kosette
Copy link
Collaborator

Kosette commented Apr 11, 2024

Emby的转码跟这几个因素有关:bitrate、videocodec、audiocodec、subtitleformat,详细的设置需要测试。

  • bitrate: 要避免转码bitrate不能设置太低,官方的推荐是设置为Auto,这个可能是根据/Playback/BitrateTest的结果动态生成的profile

  • directplay profiles:因为使用libmpv播放,所以这一块可以参考FFmpeg编码器规格,原则上几乎支持市面上大部分的编码,所以directplay profiles部分可以把常见的container、videocodec和audiocodec都写上去。

  • transcoding profiles:这一部分按照luke的说法,会优先使用codec profiles中第一个video、audio的设置,因此避免转码之后的串流太糊,需要把codec profiles中width设置的稍微大一点,比如

{
  "Type": "Video",
  "Codec": "h264",
  "Conditions": [
    {
      "Condition": "EqualsAny",
      "Property": "VideoProfile",
      "Value": "high|main|baseline|constrained baseline",
      "IsRequired": false
    },
    {
      "Condition": "LessThanEqual",
      "Property": "VideoLevel",
      "Value": "52",
      "IsRequired": false
    },
    {
      "Condition": "LessThanEqual",
      "Property": "Width",
      "Value": "1920",         <-------
      "IsRequired": false
    }
  ]
}
  • subtitle:字幕方面基本主流的srt、ass、ssa、pgssub都支持的,这一块不确定是否需要指定。

@amtoaer
Copy link
Contributor Author

amtoaer commented Apr 11, 2024

想到之前有用过一个开源的 jellyfin 客户端 findroid,去看了看他的源码。他采取的策略是 direct play only,具体设置是这样的:

https://github.com/jarnedemeulemeester/findroid/blob/a743363a8765e9fa159359a06df0f4b03e91f22a/data/src/main/java/dev/jdtech/jellyfin/repository/JellyfinRepositoryImpl.kt#L288

emby 和 jellyfin 在这方面应该差距不大,如果我们也打算仅支持 direct play 的话,可以将这个设置作为参考。

@ZBound
Copy link
Contributor

ZBound commented Apr 11, 2024

我认为转码的作用:
一是为了让某些软硬件支持一些特殊媒体流;
二是为了降低分辨率和码率使其对带宽要求降低。

前者因为是桌面端软件且使用libmpv,解码不了的媒体流应该是少数;
后者的话根据 YD/T 3328-2023 标准就算是家宽上行一般也有 30-40Mbit/s,几乎可以看大部分4k以内非原盘和Remux,况且还有使用vps搭建的方案。

我认为 direct play only 没什么问题。

@tsukinaha
Copy link
Owner

不打算做转码。
如果有合适的参数欢迎直接 pr

@Kosette
Copy link
Collaborator

Kosette commented Apr 11, 2024

@amtoaer 方便的话麻烦测试一下这个profile。 https://pastebin.com/dh9Ap8uv
具体需要修改这两行。

let profile = serde_json::json!({"DeviceProfile":{"MaxStaticBitrate":140000000,"MaxStreamingBitrate":140000000,"MusicStreamingTranscodingBitrate":192000,"DirectPlayProfiles":[{"Container":"mp4,m4v","Type":"Video","VideoCodec":"h264,av1,vp8,vp9","AudioCodec":"aac,opus,flac,vorbis"},{"Container":"flv","Type":"Video","VideoCodec":"h264","AudioCodec":"aac,mp3"},{"Container":"mov","Type":"Video","VideoCodec":"h264","AudioCodec":"aac,opus,flac,vorbis"},{"Container":"opus","Type":"Audio"},{"Container":"mp3","Type":"Audio","AudioCodec":"mp3"},{"Container":"mp2,mp3","Type":"Audio","AudioCodec":"mp2"},{"Container":"m4a","AudioCodec":"aac","Type":"Audio"},{"Container":"mp4","AudioCodec":"aac","Type":"Audio"},{"Container":"flac","Type":"Audio"},{"Container":"webma,webm","Type":"Audio"},{"Container":"wav","Type":"Audio","AudioCodec":"PCM_S16LE,PCM_S24LE"},{"Container":"ogg","Type":"Audio"},{"Container":"webm","Type":"Video","AudioCodec":"vorbis,opus","VideoCodec":"av1,VP8,VP9"}],"TranscodingProfiles":[{"Container":"aac","Type":"Audio","AudioCodec":"aac","Context":"Streaming","Protocol":"hls","MaxAudioChannels":"2","MinSegments":"1","BreakOnNonKeyFrames":true},{"Container":"aac","Type":"Audio","AudioCodec":"aac","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"mp3","Type":"Audio","AudioCodec":"mp3","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"opus","Type":"Audio","AudioCodec":"opus","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"wav","Type":"Audio","AudioCodec":"wav","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"opus","Type":"Audio","AudioCodec":"opus","Context":"Static","Protocol":"http","MaxAudioChannels":"2"},{"Container":"mp3","Type":"Audio","AudioCodec":"mp3","Context":"Static","Protocol":"http","MaxAudioChannels":"2"},{"Container":"aac","Type":"Audio","AudioCodec":"aac","Context":"Static","Protocol":"http","MaxAudioChannels":"2"},{"Container":"wav","Type":"Audio","AudioCodec":"wav","Context":"Static","Protocol":"http","MaxAudioChannels":"2"},{"Container":"m4s,ts","Type":"Video","AudioCodec":"aac","VideoCodec":"h264","Context":"Streaming","Protocol":"hls","MaxAudioChannels":"2","MinSegments":"1","BreakOnNonKeyFrames":true,"ManifestSubtitles":"vtt"},{"Container":"webm","Type":"Video","AudioCodec":"vorbis","VideoCodec":"vpx","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"mp4","Type":"Video","AudioCodec":"aac,opus,flac,vorbis","VideoCodec":"h264","Context":"Static","Protocol":"http"}],"ContainerProfiles":[],"CodecProfiles":[{"Type":"VideoAudio","Codec":"aac","Conditions":[{"Condition":"Equals","Property":"IsSecondaryAudio","Value":"false","IsRequired":"false"}]},{"Type":"VideoAudio","Conditions":[{"Condition":"Equals","Property":"IsSecondaryAudio","Value":"false","IsRequired":"false"}]},{"Type":"Video","Codec":"h264","Conditions":[{"Condition":"EqualsAny","Property":"VideoProfile","Value":"high|main|baseline|constrained baseline","IsRequired":false},{"Condition":"LessThanEqual","Property":"VideoLevel","Value":"52","IsRequired":false},{"Condition":"LessThanEqual","Property":"Width","Value":"1280","IsRequired":false}]},{"Type":"Video","Codec":"hevc","Conditions":[{"Condition":"LessThanEqual","Property":"Width","Value":"1280","IsRequired":false}]},{"Type":"Video","Conditions":[{"Condition":"LessThanEqual","Property":"Width","Value":"1280","IsRequired":false}]}],"SubtitleProfiles":[{"Format":"vtt","Method":"Hls"},{"Format":"eia_608","Method":"VideoSideData","Protocol":"hls"},{"Format":"eia_708","Method":"VideoSideData","Protocol":"hls"},{"Format":"vtt","Method":"External"},{"Format":"ass","Method":"External"},{"Format":"ssa","Method":"External"}],"ResponseProfiles":[{"Type":"Video","Container":"m4v","MimeType":"video/mp4"}]}});

let profile = serde_json::json!({"DeviceProfile":{"MaxStaticBitrate":140000000,"MaxStreamingBitrate":140000000,"MusicStreamingTranscodingBitrate":192000,"DirectPlayProfiles":[{"Container":"mp4,m4v","Type":"Video","VideoCodec":"h264,av1,vp8,vp9","AudioCodec":"aac,opus,flac,vorbis"},{"Container":"flv","Type":"Video","VideoCodec":"h264","AudioCodec":"aac,mp3"},{"Container":"mov","Type":"Video","VideoCodec":"h264","AudioCodec":"aac,opus,flac,vorbis"},{"Container":"opus","Type":"Audio"},{"Container":"mp3","Type":"Audio","AudioCodec":"mp3"},{"Container":"mp2,mp3","Type":"Audio","AudioCodec":"mp2"},{"Container":"m4a","AudioCodec":"aac","Type":"Audio"},{"Container":"mp4","AudioCodec":"aac","Type":"Audio"},{"Container":"flac","Type":"Audio"},{"Container":"webma,webm","Type":"Audio"},{"Container":"wav","Type":"Audio","AudioCodec":"PCM_S16LE,PCM_S24LE"},{"Container":"ogg","Type":"Audio"},{"Container":"webm","Type":"Video","AudioCodec":"vorbis,opus","VideoCodec":"av1,VP8,VP9"}],"TranscodingProfiles":[{"Container":"aac","Type":"Audio","AudioCodec":"aac","Context":"Streaming","Protocol":"hls","MaxAudioChannels":"2","MinSegments":"1","BreakOnNonKeyFrames":true},{"Container":"aac","Type":"Audio","AudioCodec":"aac","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"mp3","Type":"Audio","AudioCodec":"mp3","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"opus","Type":"Audio","AudioCodec":"opus","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"wav","Type":"Audio","AudioCodec":"wav","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"opus","Type":"Audio","AudioCodec":"opus","Context":"Static","Protocol":"http","MaxAudioChannels":"2"},{"Container":"mp3","Type":"Audio","AudioCodec":"mp3","Context":"Static","Protocol":"http","MaxAudioChannels":"2"},{"Container":"aac","Type":"Audio","AudioCodec":"aac","Context":"Static","Protocol":"http","MaxAudioChannels":"2"},{"Container":"wav","Type":"Audio","AudioCodec":"wav","Context":"Static","Protocol":"http","MaxAudioChannels":"2"},{"Container":"m4s,ts","Type":"Video","AudioCodec":"aac","VideoCodec":"h264","Context":"Streaming","Protocol":"hls","MaxAudioChannels":"2","MinSegments":"1","BreakOnNonKeyFrames":true,"ManifestSubtitles":"vtt"},{"Container":"webm","Type":"Video","AudioCodec":"vorbis","VideoCodec":"vpx","Context":"Streaming","Protocol":"http","MaxAudioChannels":"2"},{"Container":"mp4","Type":"Video","AudioCodec":"aac,opus,flac,vorbis","VideoCodec":"h264","Context":"Static","Protocol":"http"}],"ContainerProfiles":[],"CodecProfiles":[{"Type":"VideoAudio","Codec":"aac","Conditions":[{"Condition":"Equals","Property":"IsSecondaryAudio","Value":"false","IsRequired":"false"}]},{"Type":"VideoAudio","Conditions":[{"Condition":"Equals","Property":"IsSecondaryAudio","Value":"false","IsRequired":"false"}]},{"Type":"Video","Codec":"h264","Conditions":[{"Condition":"EqualsAny","Property":"VideoProfile","Value":"high|main|baseline|constrained baseline","IsRequired":false},{"Condition":"LessThanEqual","Property":"VideoLevel","Value":"52","IsRequired":false},{"Condition":"LessThanEqual","Property":"Width","Value":"1280","IsRequired":false}]},{"Type":"Video","Codec":"hevc","Conditions":[{"Condition":"LessThanEqual","Property":"Width","Value":"1280","IsRequired":false}]},{"Type":"Video","Conditions":[{"Condition":"LessThanEqual","Property":"Width","Value":"1280","IsRequired":false}]}],"SubtitleProfiles":[{"Format":"vtt","Method":"Hls"},{"Format":"eia_608","Method":"VideoSideData","Protocol":"hls"},{"Format":"eia_708","Method":"VideoSideData","Protocol":"hls"},{"Format":"vtt","Method":"External"},{"Format":"ass","Method":"External"},{"Format":"ssa","Method":"External"}],"ResponseProfiles":[{"Type":"Video","Container":"m4v","MimeType":"video/mp4"}]}});

@amtoaer
Copy link
Contributor Author

amtoaer commented Apr 11, 2024

@Kosette 不行,会挂:
image

@Kosette
Copy link
Collaborator

Kosette commented Apr 11, 2024

@amtoaer 我这边没有开了转码的服务器,方便的话可以给我开一个测试账号吗?我这边在没有开启转码的情况下没有复现这个情况

@ZBound
Copy link
Contributor

ZBound commented Apr 11, 2024

@Kosette 我记得Nyamedia公益服好像支持转码,你去试试

@amtoaer
Copy link
Contributor Author

amtoaer commented Apr 11, 2024

你有 tg 账号吗,可以私聊我一下,我把账号和地址发你: https://t.me/amtoaer 。或者给个邮箱也行。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants