Repository: streamlink/streamlink

Issue:
BBC iPlayer Live TV
When streaming live channels from iplayer e.g. http://www.bbc.co.uk/iplayer/live/bbcone (geoip restricted to UK) it defaults to 960x540 25fps video.

```
Streamlink:
[cli][info] Available streams: 544k_alt, 1700k_alt, 1700k_alt2, 544k_alt2, 352k_alt2, 942k_alt2, 540p_alt, 288p_alt, 942k_alt, 540p_alt2, 396p_alt2, 288p_alt2, 396p_alt, 352k_alt, 352k (worst), 544k, 288p, 942k, 396p, 540p, 1700k (best)
[cli][info] Opening stream: 1700k (hds)
```

get_iplayer had a streaming option which allows streaming up to 720p 50fps [info](https://github.com/get-iplayer/get_iplayer/wiki/modesref#tv-modes). Unfortunately the developer removed the streaming feature from new versions. 

```
get_iplayer:
INFO: hvfhd1,hvfhd2,hvfhd3,hvfhd4,hvfsd1,hvfsd2,hvfsd3,hvfsd4,hvfvhigh1,hvfvhigh2,hvfvhigh3,hvfvhigh4,hvfhigh1,hvfhigh2,hvfhigh3,hvfhigh4,hvfstd1,hvfstd2,hvfstd3,hvfstd4,hvflow1,hvflow2,hvflow3,hvflow4 modes will be tried for version default
INFO: Trying hvfhd1 mode to stream livetv: BBC One - live

 (+) Video --vid=1 (h264 1280x720 50.000fps)
 (+) Audio --aid=1 (aac 2ch 48000Hz)
```

Is it possible to force mpegdash/hls 720p 50fps stream with streamlink or would a new feature be needed to enable it?


Discussion:
It would require some development work, how much work I don't know. Unless someone else does it, I'll take a look at it at some point in the next couple of weeks. 
@h633537 wrote: 

> Is it possible to force mpegdash/hls 720p 50fps stream with streamlink

I'm not sure whether streamlink currently supports MPEG-DASH streams; youtube-dl does, but only for VOD, not live streams (dynamic manifests). 
If you are willing to do some manual labour, then you can grab yourself the AdobeHDS manifests and/or AppleHLS playlists and feed those to streamlink directly...
 
 E.g. for BBC One (London), one can sniff the mediaselector URL to the streams: 
`http://open.live.bbc.co.uk/mediaselector/5/select/version/2.0/mediaset/pc/vpid/bbc_one_london/atk/78ca5063d64bb5b308d1d87f737b610aa2db0f3f/asn/1/` 
and the hds manifest for the Akamai CDN is 
`http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/ak/bbc_one_london.f4m`

If you substitute `bbc_one_london.f4m` with `bbc_one_hd.f4m`, then 
`streamlink -o BBCOneLive.flv "hds://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/ak/bbc_one_hd.f4m" best` =>

```
[cli][info] Found matching plugin stream for URL hds://a.files.bbci.co.uk/media/
live/manifesto/audio_video/simulcast/hds/uk/pc/ak/bbc_one_hd.f4m
[cli][info] Available streams: 352k (worst), 544k, 942k, 1700k, 2908k, 5166k (be
st)
[cli][info] Opening stream: 5166k (hds)
[download][BBCOneLive.flv] Written 312.3 KB (1s @ 213.9 KB/s)
```
If you prefer AppleHLS streams, then for 
`http://open.live.bbc.co.uk/mediaselector/5/select/version/2.0/mediaset/iptv-all/vpid/bbc_one_hd` 
one gets (Akamai CDN): 
`http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hls/uk/abr_hdtv/ak/bbc_one_hd.m3u8`
so
`streamlink -o BBCOneLive.ts "hlsvariant://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hls/uk/abr_hdtv/ak/bbc_one_hd.m3u8" best` => 
```
[cli][info] Found matching plugin stream for URL hlsvariant://a.files.bbci.co.uk
/media/live/manifesto/audio_video/simulcast/hls/uk/abr_hdtv/ak/bbc_one_hd.m3u8
[cli][info] Available streams: 396p (worst), 540p, 720p (best)
[cli][info] Opening stream: 720p (hls)
[download][BBCOneLive.ts] Written 372.6 KB (0s @ 402.4 KB/s)
```
NB: Both the `mediaselector` URLs and the HDS/HLS streams themselves are geo-filtered to the UK only 
(and the BBC have a nasty habit of blocking many commercial VPS/VPN/Proxy providers...).

If you can grab a previous get_iplayer version with live TV support, then you can extract the AppleHLS playlists via the `--streaminfo` switch: 
`perl get_iplayer-297.pl --type=livetv --pid=bbc_one_hd -i --streaminfo` 
Search under the `hvfhd*` livetvmodes for `streamurl` URLs... 
Alternatively, you can use an online service 
`http://bbclive.herokuapp.com/`
Select the _Generated Playlists_ section for TV (it's hosted on an overseas server, so _Mediaselector API_ won't work for TV...).
@MickelCL 

Please take your spamming activities elsewhere; this issue (and whole tracker) IS NOT THE PLACE to promote commercial VPN solutions; be advised the iPlayer team are on a constant hunt for UK VPN services that advertise overseas access; of course they can't block every VPN out there, but once you "advertise" one the more likely it is to be blocked sooner or later... 

It looks as though you subscribed into GitHub just two weeks ago; if your sole intention was to promote spam, then think again; I am really tempted to hit that "Report abuse" button; you've been warned!
I have edited the above comment by @MickelCL to remove a direct link to a VPN provider as it has been linked here as well as #1197 
Yet another spamming intervention by github user @MickelCL [here](https://github.com/streamlink/streamlink/issues/1198#issuecomment-329156080); @gravyboat, will you edit again, warn again or simply block? 
@Vangelis66 Good catch, edited that out. In addition I have blocked them from the organization (so they can't spam any more), and reported them to GitHub. Thanks!
@gravyboat 
Look again [here](https://github.com/streamlink/streamlink/issues/1198#issuecomment-329157619), in the same issue; _probably the same person under a similar GitHub username_... 
It's just that I am allergic to spam in general, nothing personal with them or their company/service... 
If anyone's in need of the service they provide, they're free to use the search engine of their choice... 

... Come to think of it, this infringing GitHub user may not be directly related to that company, but such companies (especially the new ones in the field) have a nasty habit of promising free accounts to hopefuls that promote their product in prominent internet locations...
@Vangelis66 I totally agree with you, I'll modify the comment and ban them as well, thanks for looking out! I don't tolerate that spam either.
Some problems with live BBC:

BBC One
C:\WINDOWS\system32>streamlink https://www.bbc.co.uk/iplayer/live/bbcone
[cli][info] Found matching plugin bbciplayer for URL https://www.bbc.co.uk/iplayer/live/bbcone
[plugin.bbciplayer][info] A TV License is required to watch BBC iPlayer streams, see the BBC website for more information: https://www.bbc.co.uk/iplayer/help/tvlicence
error: Unable to open URL: http://open.live.bbc.co.uk/mediaselector/6/select/version/2.0/mediaset/pc/vpid/bbc_one/format/json/atk/a3c61c990404b5a1dea9578af356ca3187cb3c2d/asn/1/ (404 Client Error: Not Found for url: http://open.live.bbc.co.uk/mediaselector/6/select/version/2.0/mediaset/pc/vpid/bbc_one/format/json/atk/a3c61c990404b5a1dea9578af356ca3187cb3c2d/asn/1/)

the same error with BBC Two

C:\WINDOWS\system32>streamlink https://www.bbc.co.uk/iplayer/live/bbctwo

but working alright with 

BBC News

C:\WINDOWS\system32>streamlink https://www.bbc.co.uk/iplayer/live/bbcnews
[cli][info] Found matching plugin bbciplayer for URL https://www.bbc.co.uk/iplayer/live/bbcnews
[plugin.bbciplayer][info] A TV License is required to watch BBC iPlayer streams, see the BBC website for more information: https://www.bbc.co.uk/iplayer/help/tvlicence
[cli][info] Available streams: 352k_alt2 (worst), 352k_alt, 352k, 544k_alt2, 544k_alt, 544k, 942k_alt2, 942k_alt, 942k, 396p_alt2, 396p_alt, 396p, 540p_alt2, 540p_alt, 540p, 1700k_alt2, 1700k_alt, 1700k, 720p_alt2, 720p_alt, 720p, 2908k_alt2, 2908k_alt, 2908k, 5166k_alt2, 5166k_alt, 5166k (best)
[cli][info] Opening stream: 5166k (hds)
[cli][info] Starting player: "C:\mpv_64-20171225\mpv.exe" --cache=5000

and BBC Four and BBC Parliament
streamlink https://www.bbc.co.uk/iplayer/live/bbcfour
streamlink https://www.bbc.co.uk/iplayer/live/bbcparliament



EDIT:
I can watch live  BBC One and BBC Two with the following commands:

C:\WINDOWS\system32>streamlink http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hls/uk/abr_hdtv/ak/bbc_one_hd.m3u8

and 

C:\WINDOWS\system32>streamlink http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hls/uk/abr_hdtv/ak/bbc_two_hd.m3u8


Seeing the same issues
The original issue at the top is about **dash** it might work with #1637 

---

about the other two issue above this comment

it's unclear which version is used and a debug log would help

https://streamlink.github.io/cli.html#cmdoption-l
DASH support would be possible with #1637, I have a branch ready to go. The other two issues are likely fixed already, there were a couple of fixes merged but I can’t find the PRs right now.
 Vangelis66 commented on 24 Jun 2017:

http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/ak/bbc_one_london.f4m

You, sir, have been extremely helpful. 

I can now also stream BBC2 using: streamlink http://a.files.bbci.co.uk/media/live/manifesto/audio_video/simulcast/hds/uk/pc/ak/bbc_two_hd.f4m --default-stream 1700k with the CPU on my 11 year-old Vista laptop stable at approx 25%.

I don't ask much from life! Now, how to get the ITV streams working in a similar manner?

Many thanks.



Resolving patch:
diff --git a/src/streamlink/plugins/bbciplayer.py b/src/streamlink/plugins/bbciplayer.py
--- a/src/streamlink/plugins/bbciplayer.py
+++ b/src/streamlink/plugins/bbciplayer.py
@@ -2,8 +2,10 @@
 
 import base64
 import re
+from collections import defaultdict
 from hashlib import sha1
 
+from streamlink import PluginError
 from streamlink.compat import parse_qsl, urlparse
 from streamlink.plugin import Plugin, PluginOptions
 from streamlink.plugin.api import http
@@ -25,7 +27,8 @@ class BBCiPlayer(Plugin):
         )
     """, re.VERBOSE)
     mediator_re = re.compile(r'window\.mediatorDefer\s*=\s*page\([^,]*,\s*({.*?})\);', re.DOTALL)
-    tvip_re = re.compile(r'event_master_brand=(\w+?)&')
+    tvip_re = re.compile(r'channel"\s*:\s*{\s*"id"\s*:\s*"(\w+?)"')
+    tvip_master_re = re.compile(r'event_master_brand=(\w+?)&')
     account_locals_re = re.compile(r'window.bbcAccount.locals\s*=\s*({.*?});')
     swf_url = "http://emp.bbci.co.uk/emp/SMPf/1.18.3/StandardMediaPlayerChromelessFlash.swf"
     hash = base64.b64decode(b"N2RmZjc2NzFkMGM2OTdmZWRiMWQ5MDVkOWExMjE3MTk5MzhiOTJiZg==")
@@ -110,25 +113,35 @@ def find_vpid(self, url, res=None):
         vpid = m and parse_json(m.group(1), schema=self.mediator_schema)
         return vpid
 
-    def find_tvip(self, url):
-        self.logger.debug("Looking for tvip on {0}", url)
+    def find_tvip(self, url, master=False):
+        self.logger.debug("Looking for {0} tvip on {1}", "master" if master else "", url)
         res = http.get(url)
-        m = self.tvip_re.search(res.text)
+        if master:
+            m = self.tvip_master_re.search(res.text)
+        else:
+            m = self.tvip_re.search(res.text)
         return m and m.group(1)
 
     def mediaselector(self, vpid):
+        urls = defaultdict(set)
         for platform in self.platforms:
             url = self.api_url.format(vpid=vpid, vpid_hash=self._hash_vpid(vpid), platform=platform)
             self.logger.debug("Info API request: {0}", url)
-            stream_urls = http.get(url, schema=self.mediaselector_schema)
-            for media in stream_urls:
+            medias = http.get(url, schema=self.mediaselector_schema)
+            for media in medias:
                 for connection in media["connection"]:
-                    if connection.get("transferFormat") == "hds":
-                        for s in HDSStream.parse_manifest(self.session, connection["href"]).items():
-                            yield s
-                    if connection.get("transferFormat") == "hls":
-                        for s in HLSStream.parse_variant_playlist(self.session, connection["href"]).items():
-                            yield s
+                    urls[connection.get("transferFormat")].add(connection["href"])
+
+        for stream_type, urls in urls.items():
+            self.logger.debug("{0} {1} streams", len(urls), stream_type)
+            for url in list(urls):
+                self.logger.debug("  {0}", url)
+                if stream_type == "hds":
+                    for s in HDSStream.parse_manifest(self.session, url).items():
+                        yield s
+                if stream_type == "hls":
+                    for s in HLSStream.parse_variant_playlist(self.session, url).items():
+                        yield s
 
     def login(self, ptrt_url):
         """
@@ -188,6 +201,17 @@ def _get_streams(self):
                 self.logger.error("Could not find VPID for episode {0}", episode_id)
         elif channel_name:
             self.logger.debug("Loading stream for live channel: {0}", channel_name)
+            if self.get_option("hd"):
+                tvip = self.find_tvip(self.url, master=True) + "_hd"
+                if tvip:
+                    self.logger.debug("Trying HD stream {0}...", tvip)
+                    try:
+                        for s in self.mediaselector(tvip):
+                            yield s
+                    except PluginError:
+                        self.logger.error("Failed to get HD streams, falling back to SD")
+                    else:
+                        return
             tvip = self.find_tvip(self.url)
             if tvip:
                 self.logger.debug("Found TVIP: {0}", tvip)
diff --git a/src/streamlink_cli/argparser.py b/src/streamlink_cli/argparser.py
--- a/src/streamlink_cli/argparser.py
+++ b/src/streamlink_cli/argparser.py
@@ -1353,6 +1353,13 @@ def hours_minutes_seconds(value):
     A bbc.co.uk account password to use with --bbciplayer-username.
     """
 )
+plugin.add_argument(
+    "--bbciplayer-hd",
+    action="store_true",
+    help="""
+    Prefer HD streams over local SD streams, some live programmes may not be broadcast in HD. 
+    """
+)
 plugin.add_argument(
     "--zattoo-email",
     metavar="EMAIL",
diff --git a/src/streamlink_cli/main.py b/src/streamlink_cli/main.py
--- a/src/streamlink_cli/main.py
+++ b/src/streamlink_cli/main.py
@@ -955,6 +955,9 @@ def setup_plugin_options():
     if bbciplayer_password:
         streamlink.set_plugin_option("bbciplayer", "password", bbciplayer_password)
 
+    if args.bbciplayer_hd:
+        streamlink.set_plugin_option("bbciplayer", "hd", True)
+
     if args.zattoo_email:
         streamlink.set_plugin_option("zattoo", "email", args.zattoo_email)
     if args.zattoo_email and not args.zattoo_password:


Test patch: