-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
plugins.twitch: add --twitch-supported-codecs #5769
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
base: master
Are you sure you want to change the base?
plugins.twitch: add --twitch-supported-codecs #5769
Conversation
Btw, setting |
This seems to work. I've been able to watch the stream of r0dn3y with any of the selected streams working, including the 1440p120 hevc stream, but the behavior of the parameter is kind of weird. The current stream of r0dn3y offered 480p30 (avc), 720p60 (av1), 1080p60 (av1) and 1440p120 (hevc). Now when I pass |
This is not "parameter specific" and has nothing to do with the plugin implementation. It's just the data which is returned by the multivariant playlist when setting the See the examples in the OP. I have no idea why they don't return all the streams when |
I also get Edit: Actually the playlists for just |
You can enable HEVC support on firefox by setting |
h265 is irrelevant, because it's a patent encumbered codec, hence the development of AV1 by the AOM. As said in the OP, I'm surprised that Twitch even offers streams using this codec in their beta program, because this is all about AV1 support. If you request the multivariant playlists on Twitch and set There is no reason to add h265 here, because Twitch won't use it.
|
While I do understand you reasoning for preferring AV1 Twitch mentions both AV1 and HEVC on their beta page and obviously allows both AV1 and HEVC streams being served. Why not just add the value |
That is surprising, tbh... Let me update the plugin arg real quick, with support for all possible name combinations. |
62c3d06
to
535ce45
Compare
Rebased to master and made some changes to the new plugin argument setup, so the allowed argument values are defined there and not in the UsherService class. Simply sideloading the plugin from the PR branch won't work anymore. To anyone who wants to try out this PR, you'll have to install from the PR branch, because it relies on new code on the master branch. |
535ce45
to
539b77e
Compare
Free public streams (even with ad) don't require patent royalties for hevc/h.265 |
The new AV1 and H265 streams are backed by MP4 containers instead of MPEG-TS, which have slightly different streaming capabilities. MP4 is a lot more susceptible to the stream becoming corrupt if packets are dropped or partially written, MPEG-TS inherently allows this and can just re-sync the stream on errors. I'm not sure how much of a problem this is in regular use, I'm not sure if streamlink buffers whole segments before writing them or not, but I imagine at least when using |
I'm aware of them having switched the container format, but that shouldn't matter. Streamlink does support HLS maps (initialization sections), which is requirement for fMP4, so we're perfectly fine here. The error resilience of an MPEG transport stream should only be relevant for non-bi-directional data transmissions like DVB, and not for HTTP(S) connections over TCP (with TLS). Twitch is not the only platform which (now) uses fMP4 HLS streams. I've never seen such errors with other fMP4 streams which you worry about. In regards to stream discontinuities, this also shouldn't matter, because this is based on full HLS segments and not on partial segment data, and (most) decoders should be able to recover from a gap of data here as well. If |
The problem would be if something happened to the connection mid-segment download, either on the user or the server end. MP4 (ISOBMF) boxes use length prefixing, MPEG-TS uses a fixed packet size and sync bytes. If a write of an MP4 segment is interrupted without writing the specified box length, the stream will get out of sync with no way to re-sync. For MPEG-TS, the demuxer will notice that the sync byte isn't correct and it will re-sync to the next sync byte. So the problem situation is for example if there was some error in the middle of downloading segment 1000 and it was only partially written to the output, when it starts downloading and writing 1001, the demuxer would still be assuming it's reading the partially written box from segment 1000, and when it "finishes" reading the box and tries to parse the next one it will just see garbage data and be unable to continue decoding the stream. |
I consider this issue far too rare for it being relevant. A segment download would need to stop mid-way for some reason while the next segment or another one after that (#5603) would need to continue regularly, so parts of the incomplete bitstream of the previous segment get skipped. As said, this would only work when data gets streamed to the output buffer. This is not worth making sacrifices in terms of output delay or implementing bitstream inspection in Python before writing data to the output, which would be slow and also rather complex (see https://github.com/beardypig/pymp4). If a user has an unstable connection and the bitstream-continuation of the HLS segments can't be guaranteed due to that, then they shouldn't set the stream option (which also gets enabled when |
I agree it's probably a rare issue, so not sure if it's worth pursuing, but I also don't really think it would be that complex. You don't have to implement full MP4 parsing, you just need to parse the first 32 bits of the top-level box to get the length, buffer that amount, and then write it out, and repeat. If the segment EOFs before the length amount is read, discard the buffer. The buffer would only have to hold the single largest box, which in an fMP4 stream should be fairly small (kilobytes range). |
It's March now... Have there been any developments on the side of Twitch? |
@bastimeyer I have not seen anything from them regarding this. |
This comment was marked as off-topic.
This comment was marked as off-topic.
A timeline has not been announced. Though AV1/HEVC is intended to be experimented with more widely as part of the Enhanced Broadcasting beta. So it'll be more than just my channel soon™ |
OBS Studio 30.2 Beta 1 is out which adds general support for multitrack video encoding ("Enhanced Broadcasting"). It seems Twitch is still rolling out support for this on a per-account basis, there's also this notice on their announcement page:
|
Multitrack streaming with just AVC/H.264 is now available as a public beta, HEVC/AV1 are still later and will be limited to the closed beta group first. |
As a little update: There are now a few bigger streamers that have been given the opportunity to trial 4K HEVC streaming, such as maximilian_dood, burkeblack, and EposVox. So this would be nice to have. |
I tested the changes for recording twitch streams locally. The CLI works and can record the best quality HEVC stream to an output file. However, the recording seems to have like incorrect metadata. Playing the recording in mpv shows a start time that is the duration of the stream when the recording began + 1 minute. It's strangely very close if not exactly 1 minute ahead of the stream duration. For example, if a stream has gone on for 3:43:00 and you start recording, the recording will start at 3:44:00 even though it should start at 0:00:00. The video otherwise plays correctly what was recorded. Playing the recording in browser shows the correct length of like 10 seconds, but struggles to play it by stopping and waiting for some time before resuming repeatedly as if it was buffering. I ran ffprobe on the file and the duration lines up with what mpv is seeing. I tested recording a normal h264 livestream and it still works as normal with the starting timestamp being 0. Also, trying to extract the stream urls through the Python API does not return any h265 m3u8 links. I only tested on an h265 stream so I am unsure if it would find AV1 links if available. Seems like only CLI is working. |
This is a side effect of the container format being different on Twitch for H264 vs H265/AV1 streams. H264 uses MPEGTS and H265/AV1 uses MP4. Both of the containers have the same timestamp information inside of them, but mpv/ffmpeg chooses to display them differently between MPEGTS and MP4. You should be able to "fix" this by remuxing the stream with ffmpeg, which by default shifts the start timestamp back to 0.
|
Thanks for the info. Didn't realize that's what it was. Was hoping I didn't have to remux, but oh well. |
use the options |
We can wrap all instances of The solution however is a really ugly hack, on top of this non-ideal plugin-argument implementation, until the entire stream selection logic has been rewritten (#4902 / #5764). It should still work fine though. Let me rebase this, so you can check... Current:
Updated:
|
4a8e25b
to
7babe6e
Compare
Seems to work perfect for me. The recording starts at 0 in mpv and it plays perfectly. Definitely a nicer solution for me. Many thanks for adding this. Edit: Actually, there is one issue that wasn't there before. If you jump around an HEVC recording while using mpv, it will look pixelated as if there was a drop in bitrate or the streamer had connection issues. After a moment to a few seconds, it looks perfectly fine. The video itself is fine and if you don't seek or jump around, it looks perfect with no issues. PotPlayer has no issue with seeking and looks perfect. It intuitively seems to me that mpv needs time to process before it starts displaying the video correctly and potplayer is doing something more advanced to not have this problem. Edit 2: Actually, I suspect the seeking issues is an ffmpeg bug with how it handles mpeg ts files that use hevc based on ffmpeg having an open issue on that topic. Remuxing the recorded produces files that seek perfectly fine. |
2k HEVC streaming was released to all affiliates and partners last week. I suspect a lot of streamers are going to use this from now on. While its still in beta, there is 10000 viewers watching high res streams right now, maybe its time to merge to main? |
But HEVC isn't H.265 codec? That's a licensing nightmare... |
7babe6e
to
1db934a
Compare
I've just rebased the PR branch onto master and fixed a few minor things. We should be able to merge this soon if there are no issues with the streams. But as said in #5769 (comment), I don't like this solution at all. |
1db934a
to
e4d6e32
Compare
It should probably be noted that Twitch has both geolocked and login-gated AV1/HEVC streams, so auth data (and maybe a proxy if you're not in an approved country) is need to get these streams in the playlist response. Regarding the It might be worth considering forcing |
Any ids that are geolocked to test? |
It's been reported that any countries outside the following won't receive HEVC/AV1 streams, even when logged in: |
@Hakkin Any examples of vods geo restricted? But I mean the entire vod not some renditions or qualities. |
@Hakkin these are all good points
We can add a note to the plugin-argument's help text about region restrictions.
Actually true. FFmpeg apparently doesn't set the timestamps to 0 and the timestamps are still anchored to the beginning of the broadcast. This wasn't the case when I added this commit to the PR initially IIRC. No idea what happened... While it doesn't cause any problems in mpv at least, I haven't tested any other players yet. The playback timeline being anchored to the start of the broadcast is also a bit annoying if you have set a backbuffer, because the visuals for this will be affected by the timestamps. I'll need to have another look at this.
Yes, this might actually be necessary because there are ads (of course). This also makes me question whether we can even remove the MuxedHLSStream wrapper, because certain players that don't rely on FFmpeg could probably have an issue with discontinuities. mpv at least (with and without the muxedhlsstream wrapper) continues its playback with garbage image data and no sound, and then it recovers when the correct stream's data arrives again. With the ads being filtered out, garbage data is only visible for a fraction of a second once the playback continues. It would probably even make sense renaming --twitch-disable-ads to --twitch-enable-ads and making the plugin filter out ad segments by default. Since we request the |
Add the temporary `--twitch-supported-codecs` plugin argument for being able to set the client's video codec preference. Set the default value to "h264" to ensure that no compatibility issues arise on clients without AV1/HEVC decode capabilities.
e4d6e32
to
6287cfc
Compare
6287cfc
to
9ed6496
Compare
Apparently, this is not correct. I've checked a couple of streams, and The channel I have a local branch with a refactor and cleanup of 9ed6496 that I wanted to push as a separate PR, but now I'm not so sure about this anymore. Another solution could be in combination with this PR and always requesting The "proper" solution would be requesting all the media playlists and checking whether there's a segment whose URL ends with So I guess the |
I'm still not really convinced such a hack is necessary, in all my testing there's 0 issues with streaming the un-remuxed fMP4 streams from Twitch, besides "the number doesn't start from 0". Playback and seeking both work correctly in mpv and VLC (obviously attempting to seek to a period before the stream was actually downloaded doesn't work, but that's expected). Maybe it would be easier to just include a |
No. That would require lots and lots of code refactorings and reimplementations if done generically (not plugin-specific) which would then be totally unnecessary duplicate work considering that #4902 will have to be resolved eventually anyway. This is also the reason why the codec selection is done here locally in the plugin.
To be honest, I'm also thinking that remuxing is unnecessary. Sure, the timestamp offset is annoying, but it doesn't affect playback. For local recordings, people can always remux themselves afterwards, or even on-the-fly. |
9ed6496
to
c057884
Compare
Add the temporary
--twitch-supported-codecs
plugin argument for being able to set the client's video codec preference.Set the default value to "h264" to ensure that no compatibility issues arise on clients without AV1 decode capabilities.
Resolves #5768
The set of returned streams by Twitch depends on the broadcast and which codec(s) the channel uses for its stream upload(s) (channels can now upload multiple qualities at once according to the Nvidia announcement from a couple of days ago where they talked about their Twitch and OBS partnership on that matter).
There doesn't appear to be any re-encoding in AV1 done by Twitch (yet) and from what it looks like, only one "480p" h264 stream is included as a fallback when
av1,h264
is chosen.No idea why
av1
does include one720p60
h265
(hvc1
/HEVC
) stream.av1,h264
does not. It's possible that this is just forwarded from the user's input who also uploads anh265
stream (which Twitch accepts for some reason)...h264
av1
av1,h264