Skip to content

plugins.svtplay: rewrite plugin and add HLS #4994

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

Merged
merged 1 commit into from
Nov 28, 2022

Conversation

bastimeyer
Copy link
Member

Resolves #4992

This is a full plugin rewrite which cleans up the API request and validation schema, and it adds support for HLS streams.

As you can see, there's a stream priority list, because apparently there's a difference between the available qualities of the available stream types, and for some reason, some DASH streams offer higher resolutions and bitrates. It's probably an overkill having all kinds of formats there, but whatever... Also a pretty good reason for a rewrite of the stream selection, as described in #4902.

I can access the API and VOD content with my VPN, but HLS live streams return a 403, so I can't actually test all plugin changes.

@mkbloke, please have a look, thanks.

@bastimeyer bastimeyer added plugin issue A Plugin does not work correctly restriction: geo blocked labels Nov 23, 2022
@mkbloke
Copy link
Member

mkbloke commented Nov 24, 2022

Looks like the live channels are off-air now. Will check them out later today.

@mkbloke
Copy link
Member

mkbloke commented Nov 24, 2022

SVT1, SVT2 and Kunskapskanalen are working. SVT24 is off-air till later. I notice with SVTBarn (https://www.svtplay.se/kanaler/svtbarn) making the API request with ch-svtbarn results in a binary response. The API request for that channel seems to be made with ch-barnkanalen. You can test it via curl.

$ streamlink --http-proxy 'socks5://localhost:8888' 'https://www.svtplay.se/kanaler/svt1' video
[cli][info] Found matching plugin svtplay for URL https://www.svtplay.se/kanaler/svt1
[cli][info] Available streams: video, video_alt2
[cli][info] Opening stream: video (hls-multi)
[cli][info] Starting player: mpv
[utils.named_pipe][info] Creating pipe streamlinkpipe-447613-1-6774
[utils.named_pipe][info] Creating pipe streamlinkpipe-447613-2-3982
[cli][info] Player closed
[stream.ffmpegmux][error] Pipe copy aborted: /tmp/streamlinkpipe-447613-1-6774
[cli][info] Stream ended
[cli][info] Closing currently open stream...

$ streamlink --http-proxy 'socks5://localhost:8888' 'https://www.svtplay.se/kanaler/kunskapskanalen' best
[cli][info] Found matching plugin svtplay for URL https://www.svtplay.se/kanaler/kunskapskanalen
[cli][info] Available streams: 234p (worst), 360p, 540p, 720p_alt, 720p (best)
[cli][info] Opening stream: 720p (dash)
[cli][info] Starting player: mpv
[utils.named_pipe][info] Creating pipe streamlinkpipe-448386-1-249
[utils.named_pipe][info] Creating pipe streamlinkpipe-448386-2-9903
[cli][info] Player closed
[stream.ffmpegmux][error] Pipe copy aborted: /tmp/streamlinkpipe-448386-1-249
[cli][info] Stream ended
[cli][info] Closing currently open stream...

I'll have a look at SVT24 later and check a few VODs also.

@DanOscarsson
Copy link

By adding python 3.9 to my opensuse leap 15.3 I got it to work.

For www.svtplay.se/kanaler/svt1 I cannot use "best" to get best stream.
And what I can get by using video or video_alt2 is very low quality (like 640x360 pixels).
Before "best" would select at least a 720p stream.
So it looks like something have changed so the plugin cannot find the good streams.

@mkbloke
Copy link
Member

mkbloke commented Nov 24, 2022

VODs that have subs without using --mux-subtitles play fine:

$ streamlink --http-proxy 'socks5://localhost:8888' 'https://www.svtplay.se/video/jnD6nar/allra-affaren/1-det-borjade-i-en-kallare?id=jnD6nar' 360p
[cli][info] Found matching plugin svtplay for URL https://www.svtplay.se/video/jnD6nar/allra-affaren/1-det-borjade-i-en-kallare?id=jnD6nar
[cli][info] Available streams: 234p (worst), 360p, 540p, 720p, 1080p (best)
[cli][info] Opening stream: 360p (dash)
[cli][info] Starting player: mpv
[utils.named_pipe][info] Creating pipe streamlinkpipe-454473-1-3521
[utils.named_pipe][info] Creating pipe streamlinkpipe-454473-2-4769
[cli][info] Player closed
[stream.ffmpegmux][error] Pipe copy aborted: /tmp/streamlinkpipe-454473-2-4769
[stream.ffmpegmux][error] Pipe copy aborted: /tmp/streamlinkpipe-454473-1-3521
[stream.dash][warning] Download of segment: cmaf-audio-stereo-1-60.mp4 aborted
[stream.dash][warning] Download of segment: cmaf-video-avc-1-51.mp4 aborted
[cli][info] Stream ended
[cli][info] Closing currently open stream...

With muxing, sometimes, but not always, closing the player results in Streamlink producing an exception. I imagine this is not specific to the plugin though and is timing related. The VODs otherwise play fine and display the subs (once selected in mpv).

I'll just include this for info:

$ streamlink -l debug --http-proxy 'socks5://localhost:8888' --mux-subtitles 'https://www.svtplay.se/video/jp3bgRP/att-fa-syskon/10-chokladbollar?id=jp3bgRP' 360p
[session][debug] Plugin svtplay is being overridden by /home/user/.local/share/streamlink/plugins/svtplay.py
[cli][debug] OS:         Linux-5.4.0-132-generic-x86_64-with-glibc2.29
[cli][debug] Python:     3.8.10
[cli][debug] Streamlink: 5.1.0+5.gb45e685f
[cli][debug] Dependencies:
[cli][debug]  certifi: 2022.9.24
[cli][debug]  isodate: 0.6.1
[cli][debug]  lxml: 4.9.1
[cli][debug]  pycountry: 22.3.5
[cli][debug]  pycryptodome: 3.15.0
[cli][debug]  PySocks: 1.7.1
[cli][debug]  requests: 2.28.1
[cli][debug]  urllib3: 1.26.12
[cli][debug]  websocket-client: 1.4.2
[cli][debug] Arguments:
[cli][debug]  url=https://www.svtplay.se/video/jp3bgRP/att-fa-syskon/10-chokladbollar?id=jp3bgRP
[cli][debug]  stream=['360p']
[cli][debug]  --loglevel=debug
[cli][debug]  --player=mpv
[cli][debug]  --mux-subtitles=True
[cli][debug]  --http-proxy=socks5://localhost:8888
[cli][info] Found matching plugin svtplay for URL https://www.svtplay.se/video/jp3bgRP/att-fa-syskon/10-chokladbollar?id=jp3bgRP
[plugins.svtplay][debug] VOD ID=jp3bgRP
[utils.l10n][debug] Language code: en_GB
[stream.dash][debug] Available languages for DASH audio streams: sv (using: sv)
[cli][info] Available streams: 234p (worst), 360p, 540p, 720p, 1080p (best)
[cli][info] Opening stream: 360p (muxed-stream)
[cli][info] Starting player: mpv
[stream.ffmpegmux][debug] Opening dash substream
[stream.dash][debug] Opening DASH reader for: 3 (video/mp4)
[stream.dash][debug] Opening DASH reader for: 5 (audio/mp4)
[stream.dash_manifest][debug] Generating segment timeline for static playlist (id=3))
[stream.dash_manifest][debug] Generating segment timeline for static playlist (id=5))
[stream.dash][debug] Download of segment: cmaf-video-avc-640x360p25-797-init.mp4 complete
[stream.ffmpegmux][debug] ffmpeg version 4.2.7-0ubuntu0.1 Copyright (c) 2000-2022 the FFmpeg developers
[stream.ffmpegmux][debug]  built with gcc 9 (Ubuntu 9.4.0-1ubuntu1~20.04.1)
[stream.ffmpegmux][debug]  configuration: --prefix=/usr --extra-version=0ubuntu0.1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-nvenc --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
[stream.ffmpegmux][debug]  libavutil      56. 31.100 / 56. 31.100
[stream.ffmpegmux][debug]  libavcodec     58. 54.100 / 58. 54.100
[stream.ffmpegmux][debug]  libavformat    58. 29.100 / 58. 29.100
[stream.ffmpegmux][debug]  libavdevice    58.  8.100 / 58.  8.100
[stream.ffmpegmux][debug]  libavfilter     7. 57.100 /  7. 57.100
[stream.ffmpegmux][debug]  libavresample   4.  0.  0 /  4.  0.  0
[stream.ffmpegmux][debug]  libswscale      5.  5.100 /  5.  5.100
[stream.ffmpegmux][debug]  libswresample   3.  5.100 /  3.  5.100
[stream.ffmpegmux][debug]  libpostproc    55.  5.100 / 55.  5.100
[utils.named_pipe][info] Creating pipe streamlinkpipe-457003-1-8349
[utils.named_pipe][info] Creating pipe streamlinkpipe-457003-2-2018
[stream.ffmpegmux][debug] ffmpeg command: /usr/bin/ffmpeg -nostats -y -i /tmp/streamlinkpipe-457003-1-8349 -i /tmp/streamlinkpipe-457003-2-2018 -c:v copy -c:a copy -copyts -f matroska pipe:1
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/streamlinkpipe-457003-1-8349
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/streamlinkpipe-457003-2-2018
[stream.ffmpegmux][debug] Opening http subtitle stream
[stream.dash][debug] Download of segment: cmaf-video-avc-640x360p25-797-1.mp4 complete
[stream.dash][debug] Download of segment: cmaf-audio-aac-2ch-192-init.mp4 complete
[stream.dash][debug] Download of segment: cmaf-audio-aac-2ch-192-1.mp4 complete
[stream.dash][debug] Download of segment: cmaf-video-avc-640x360p25-797-2.mp4 complete
[utils.named_pipe][info] Creating pipe streamlinkpipe-457003-3-2958
[utils.named_pipe][info] Creating pipe streamlinkpipe-457003-4-9454
[stream.ffmpegmux][debug] ffmpeg command: /usr/bin/ffmpeg -nostats -y -i /tmp/streamlinkpipe-457003-3-2958 -i /tmp/streamlinkpipe-457003-4-9454 -c:v copy -c:a copy -map 0 -map 1 -metadata:s:s:0 language=webvtt -f matroska pipe:1
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/streamlinkpipe-457003-3-2958
[stream.ffmpegmux][debug] Starting copy to pipe: /tmp/streamlinkpipe-457003-4-9454
[cli][debug] Pre-buffering 8192 bytes
[stream.dash][debug] Download of segment: cmaf-audio-aac-2ch-192-2.mp4 complete
[stream.ffmpegmux][debug] Pipe copy complete: /tmp/streamlinkpipe-457003-4-9454
[cli.output][debug] Opening subprocess: mpv --force-media-title=https://www.svtplay.se/video/jp3bgRP/att-fa-syskon/10-chokladbollar?id=jp3bgRP -
[stream.dash][debug] Download of segment: cmaf-audio-aac-2ch-192-3.mp4 complete
[stream.dash][debug] Download of segment: cmaf-video-avc-640x360p25-797-3.mp4 complete
[stream.dash][debug] Download of segment: cmaf-audio-aac-2ch-192-4.mp4 complete
[stream.dash][debug] Download of segment: cmaf-video-avc-640x360p25-797-4.mp4 complete
[stream.dash][debug] Download of segment: cmaf-audio-aac-2ch-192-5.mp4 complete
[cli][debug] Writing stream to output
[stream.dash][debug] Download of segment: cmaf-video-avc-640x360p25-797-5.mp4 complete
[stream.dash][debug] Download of segment: cmaf-audio-aac-2ch-192-6.mp4 complete
...
[stream.segmented][debug] Closing worker thread
[stream.dash][debug] Download of segment: cmaf-video-avc-640x360p25-797-32.mp4 complete
...
[cli][info] Player closed
[stream.ffmpegmux][debug] Closing ffmpeg thread
[stream.ffmpegmux][debug] Closing ffmpeg thread
Exception in thread Thread-4:
Traceback (most recent call last):
  File "/usr/lib/python3.8/threading.py", line 932, in _bootstrap_inner
[stream.ffmpegmux][error] Pipe copy aborted: /tmp/streamlinkpipe-457003-2-2018
[stream.segmented][debug] Closing worker thread
[stream.ffmpegmux][error] Pipe copy aborted: /tmp/streamlinkpipe-457003-1-8349
    self.run()
[stream.segmented][debug] Closing writer thread
  File "/usr/lib/python3.8/threading.py", line 870, in run
[stream.segmented][debug] Closing writer thread
[stream.ffmpegmux][debug] Pipe copy complete: /tmp/streamlinkpipe-457003-2-2018
[stream.ffmpegmux][debug] Pipe copy complete: /tmp/streamlinkpipe-457003-1-8349
    self._target(*self._args, **self._kwargs)
  File "/home/user/.local/pipx/venvs/streamlink/lib/python3.8/site-packages/streamlink/stream/ffmpegmux.py", line 137, in copy_to_pipe
    data = stream.read(8192)
  File "/home/user/.local/pipx/venvs/streamlink/lib/python3.8/site-packages/streamlink/stream/ffmpegmux.py", line 214, in read
    return self.process.stdout.read(size)
ValueError: read of closed file
[stream.dash][warning] Download of segment: cmaf-audio-aac-2ch-192-79.mp4 aborted
[stream.dash][warning] Download of segment: cmaf-video-avc-640x360p25-797-39.mp4 aborted
[stream.ffmpegmux][debug] Closed all the substreams
[stream.ffmpegmux][debug] Closed all the substreams
[cli][info] Stream ended
[cli][info] Closing currently open stream...

@mkbloke
Copy link
Member

mkbloke commented Nov 24, 2022

@DanOscarsson, I don't know if those streams are available now (although they could be via the API). The web player only seems to offer the default quality (video_alt2 in Streamlink which is 640x360) and a limited bandwidth option which must be the video quality in Streamlink which is 416x234.

Looking at what the API returns, for example, for HLS:

$ curl --proxy 'socks5://localhost:8888' 'https://svt-secure-c.akamaized.net/secure/svt1/master.m3u8?defaultSubLang=1'
#EXTM3U
#EXT-X-VERSION:4
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-MEDIA:TYPE=AUDIO,URI="5eff9010-33e6-4944-b906-1e885e20d659/hls-a0/a0.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls",GROUP-ID="stereo",LANGUAGE="sv",NAME="Svenska",DEFAULT=YES,AUTOSELECT=YES,CHANNELS="2"
#EXT-X-MEDIA:TYPE=AUDIO,URI="5eff9010-33e6-4944-b906-1e885e20d659/hls-a1/a1.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls",GROUP-ID="stereo",LANGUAGE="sv-x-tal",NAME="Uppläst undertext",DEFAULT=NO,AUTOSELECT=NO,CHANNELS="2"
#EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="video",NAME="Video",DEFAULT=YES,AUTOSELECT=YES
#EXT-X-MEDIA:TYPE=SUBTITLES,URI="5eff9010-33e6-4944-b906-1e885e20d659/hls-s0/s0.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls",GROUP-ID="subs",LANGUAGE="sv",NAME="Svenska",DEFAULT=NO,AUTOSELECT=YES,CHARACTERISTICS="public.accessibility.transcribes-spoken-dialog,public.accessibility.describes-music-and-sound"
#EXT-X-STREAM-INF:BANDWIDTH=2699000,AVERAGE-BANDWIDTH=1933000,CODECS="avc1.64001F,mp4a.40.2",RESOLUTION=960x540,FRAME-RATE=50.0,AUDIO="stereo",VIDEO="video",SUBTITLES="subs",CLOSED-CAPTIONS=NONE
5eff9010-33e6-4944-b906-1e885e20d659/hls-v2/v2.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls
#EXT-X-STREAM-INF:BANDWIDTH=585000,AVERAGE-BANDWIDTH=472000,CODECS="avc1.42C015,mp4a.40.2",RESOLUTION=416x234,FRAME-RATE=50.0,AUDIO="stereo",VIDEO="video",SUBTITLES="subs",CLOSED-CAPTIONS=NONE
5eff9010-33e6-4944-b906-1e885e20d659/hls-v0/v0.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls
#EXT-X-STREAM-INF:BANDWIDTH=1286000,AVERAGE-BANDWIDTH=1020000,CODECS="avc1.64001F,mp4a.40.2",RESOLUTION=640x360,FRAME-RATE=50.0,AUDIO="stereo",VIDEO="video",SUBTITLES="subs",CLOSED-CAPTIONS=NONE
5eff9010-33e6-4944-b906-1e885e20d659/hls-v1/v1.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls
#EXT-X-STREAM-INF:BANDWIDTH=5120000,AVERAGE-BANDWIDTH=3874000,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=50.0,AUDIO="stereo",VIDEO="video",SUBTITLES="subs",CLOSED-CAPTIONS=NONE
5eff9010-33e6-4944-b906-1e885e20d659/hls-v3/v3.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls
#EXT-X-STREAM-INF:BANDWIDTH=6334000,AVERAGE-BANDWIDTH=5035000,CODECS="avc1.640020,mp4a.40.2",RESOLUTION=1280x720,FRAME-RATE=50.0,AUDIO="stereo",VIDEO="video",SUBTITLES="subs",CLOSED-CAPTIONS=NONE
5eff9010-33e6-4944-b906-1e885e20d659/hls-v4/v4.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls
#EXT-X-I-FRAME-STREAM-INF:URI="5eff9010-33e6-4944-b906-1e885e20d659/hls-v0/v0-i.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls",BANDWIDTH=65000,CODECS="avc1.42C015",RESOLUTION=416x234
#EXT-X-I-FRAME-STREAM-INF:URI="5eff9010-33e6-4944-b906-1e885e20d659/hls-v1/v1-i.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls",BANDWIDTH=187000,CODECS="avc1.64001F",RESOLUTION=640x360
#EXT-X-I-FRAME-STREAM-INF:URI="5eff9010-33e6-4944-b906-1e885e20d659/hls-v2/v2-i.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls",BANDWIDTH=282000,CODECS="avc1.64001F",RESOLUTION=960x540
#EXT-X-I-FRAME-STREAM-INF:URI="5eff9010-33e6-4944-b906-1e885e20d659/hls-v3/v3-i.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls",BANDWIDTH=399000,CODECS="avc1.640020",RESOLUTION=1280x720
#EXT-X-I-FRAME-STREAM-INF:URI="5eff9010-33e6-4944-b906-1e885e20d659/hls-v4/v4-i.m3u8?aka_me_session_id=AAAAAAAAAAD4AYFjAAAAAGMhreGmoGoaF73iHC3bHBPM3kZC5TfTv8ctiSdtaHLS4vpSVdN56FdTDrFEbWYOacbkiQ%2f7jUbL&aka_media_format_type=hls",BANDWIDTH=509000,CODECS="avc1.640020",RESOLUTION=1280x720

would seem to indicate more resolutions, but it seems they only resolve to two:

$ streamlink --http-proxy 'socks5://localhost:8888' 'https://svt-secure-c.akamaized.net/secure/svt1/master.m3u8?defaultSubLang=1'
[cli][info] Found matching plugin hls for URL https://svt-secure-c.akamaized.net/secure/svt1/master.m3u8?defaultSubLang=1
Available streams: video, video_alt2

@DanOscarsson
Copy link

If I use the web page in my firefox I get a very good resolution.
So the plugin is not doing the same handling as the web browser as it can only get the very low resolution streams.

@mkbloke
Copy link
Member

mkbloke commented Nov 25, 2022

OK, I looked at this a bit more, using mpv instead of Streamlink's hls plugin. There is something strange with Streamlink's parsing of the playlist it would seem. Here's what mpv reports for the stream types available for SVT1:

fmt=hls; fmt=hlswebvtt
     Video --vid=1 (*) 'bitrate 2699000' (h264 960x540 50.000fps)
     Video --vid=2 (*) 'bitrate 585000' (h264 416x234 50.000fps)
     Video --vid=3 (*) 'bitrate 1286000' (h264 640x360 50.000fps)
     Video --vid=4 (*) 'bitrate 5120000' (h264 1280x720 50.000fps)
 (+) Video --vid=5 (*) 'bitrate 6334000' (h264 1280x720 50.000fps)
 (+) Audio --aid=1 --alang=sv (*) 'bitrate 6334000' (aac 2ch 48000Hz)
     Audio --aid=2 --alang=sv-x-tal 'bitrate 6334000' (aac 2ch 48000Hz)

fmt=hls-cmaf-live; fmt=hls-cmaf-live-vtt
     Video --vid=1 (*) 'bitrate 2610000' (h264 960x540 50.000fps)
     Video --vid=2 (*) 'bitrate 536000' (h264 416x234 50.000fps)
     Video --vid=3 (*) 'bitrate 1222000' (h264 640x360 50.000fps)
     Video --vid=4 (*) 'bitrate 4924000' (h264 1280x720 50.000fps)
 (+) Video --vid=5 (*) 'bitrate 6073000' (h264 1280x720 50.000fps)
 (+) Audio --aid=1 --alang=sv (*) 'bitrate 6073000' (aac 2ch 48000Hz)
     Audio --aid=2 --alang=sv-x-tal 'bitrate 6073000' (aac 2ch 48000Hz)

@bastimeyer
Copy link
Member Author

would seem to indicate more resolutions, but it seems they only resolve to two:
There is something strange with Streamlink's parsing of the playlist

No, it just defaults to name_fmt="{name}" when building the list of media streams in HLSStream.parse_variant_playlist(). The HLS playlist names all video streams "video" and all audio streams "audio". Since only one unique stream name can get returned and only one alternative streams will be included, the result is what you're seeing, which is correct. The plugin needs to set the name_fmt to {pixels} or {bitrate}.

$ streamlink 'hls://https://svt-secure-c.akamaized.net/secure/svt1/master.m3u8?defaultSubLang=1 name_fmt={pixels}'
[cli][info] Found matching plugin hls for URL hls://https://svt-secure-c.akamaized.net/secure/svt1/master.m3u8?defaultSubLang=1 name_fmt={pixels}
Available streams: 234p (worst), 360p, 540p, 720p_alt, 720p (best)

@mkbloke
Copy link
Member

mkbloke commented Nov 25, 2022

Just worked that out at the same time!

@bastimeyer bastimeyer force-pushed the plugins/svtplay/rewrite branch from 057ad5a to 8322f88 Compare November 25, 2022 16:58
@bastimeyer
Copy link
Member Author

I've set it to {pixels}_{bitrate}, so it doesn't generate alt streams for the same res:

Available streams: 234p_580k (worst), 360p_1300k, 540p_2700k, 720p_5100k, 720p_6300k (best)

@bastimeyer
Copy link
Member Author

With muxing, sometimes, but not always, closing the player results in Streamlink producing an exception.

This is an issue with the FFMPEGMuxer's copy_to_pipe thread, where it apparently raises ValueError instead of an OSError when a read failure occurs during the nested muxing of the video+audio first, and afterward the combination of those with the subtitles. This is all really messy, and I don't know why there's a ValueError. This needs to be fixed separately. If subtitles are not important, then they can simply be removed from the plugin for now.

@bastimeyer
Copy link
Member Author

ValueError can get raised when trying to read a closed stream.
https://docs.python.org/3/library/io.html#io.IOBase
Is this related to #4972? I haven't seen this issue yet.

@DanOscarsson
Copy link

A have done just a very quick test with the new version at my place.
It looks like for me it works fine. My usage is just mostly the live streams.
Will use it in my normal way later today.
For non live streams there is an other program to download those, it you have problems.

How do you find the svt-secure-c URLs from the svtplay URL?

@mkbloke
Copy link
Member

mkbloke commented Nov 25, 2022

How do you find the svt-secure-c URLs from the svtplay URL?

curl https://api.svt.se/videoplayer-api/video/ch-svt1 | jq .videoReferences

@mkbloke
Copy link
Member

mkbloke commented Nov 25, 2022

Regarding SVTBarn, perhaps just maintaining a dict that can be updated as necessary will do the job...

--- svtplay.py.orig	2022-11-25 17:55:14.703923684 +0000
+++ svtplay.py	2022-11-25 19:58:59.968992830 +0000
@@ -28,6 +28,7 @@
 )
 class SVTPlay(Plugin):
     _URL_API_VIDEO = "https://api.svt.se/videoplayer-api/video/{item}"
+    _LIVE_API_SLUG = {"svtbarn": "barnkanalen"}
 
     def _api_call(self, item):
         _schema_items = validate.all(
@@ -69,6 +70,9 @@
         if not live_id:
             return
 
+        if live_id in self._LIVE_API_SLUG:
+            live_id = self._LIVE_API_SLUG[live_id]
+
         live_id = f"ch-{live_id}"
         log.debug(f"Live ID={live_id}")
         self.category = "Live"

@bastimeyer
Copy link
Member Author

bastimeyer commented Nov 25, 2022

The API channel names are mapped like this according to the JS:

!function(n) {
  n.SVT1 = "ch-svt1",
  n.SVT2 = "ch-svt2",
  n.BARNKANALEN = "ch-barnkanalen",
  n.KUNSKAPSKANALEN = "ch-kunskapskanalen",
  n.SVT24 = "ch-svt24"
}(le || (le = {}));
switch (n) {
  case Ae.SVT1:
    return "svt1";
  case Ae.SVT2:
    return "svt2";
  case Ae.BARNKANALEN:
    return "svtbarn";
  case Ae.KUNSKAPSKANALEN:
    return "kunskapskanalen";
  case Ae.SVT24:
    return "svt24";
  default:
    return null
}

@mkbloke
Copy link
Member

mkbloke commented Nov 25, 2022

The API channel names are mapped like this according to the JS:

I found those. I wasn't sure if it was worth mapping all of them and didn't think it would be worthwhile extracting from JS...

Whatever you think is best.

@bastimeyer bastimeyer force-pushed the plugins/svtplay/rewrite branch from 8322f88 to bd222f0 Compare November 25, 2022 20:55
@mkbloke mkbloke merged commit 55b5852 into streamlink:master Nov 28, 2022
@bastimeyer bastimeyer deleted the plugins/svtplay/rewrite branch November 28, 2022 20:49
Billy2011 added a commit to Billy2011/streamlink-27 that referenced this pull request Dec 10, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
plugin issue A Plugin does not work correctly restriction: geo blocked
Projects
None yet
Development

Successfully merging this pull request may close these issues.

plugins.svtplay: No streams found on svt1+svt2
3 participants