chrippa / livestreamer

Command-line utility that extracts streams from various services and pipes them into a video player of choice. No longer maintained, use streamlink or youtube-dl instead.
http://livestreamer.io/
BSD 2-Clause "Simplified" License
3.88k stars 582 forks source link

Afreecatv service changed. New afreeca.py #1606

Open trocknet opened 7 years ago

trocknet commented 7 years ago
import re

from livestreamer.plugin import Plugin
from livestreamer.plugin.api import http, validate
from livestreamer.stream import RTMPStream, HLSStream

CHANNEL_INFO_URL = "http://live.afreeca.com:8057/api/get_broad_state_list.php"
KEEP_ALIVE_URL = "{server}/stream_keepalive.html"
STREAM_INFO_URLS = "http://resourcemanager.afreeca.tv:9090/broad_stream_assign.html"
HLS_KEY_URL = "http://live.afreecatv.com:8057/afreeca/player_live_api.php"

CHANNEL_RESULT_ERROR = 0
CHANNEL_RESULT_OK = 1

QUALITYS=["original", "hd", "sd"]

QUALITY_WEIGHTS = {
    "gs_original": 1080,
    "gs_hd": 720,
    "gs_sd": 480,
    "aws_original": 1081,
    "aws_hd": 721,
    "aws_sd": 481,
}

CDN_SITES = {
    "gs": "gs_cdn",
    "aws": "aws_cf"
}

_url_re = re.compile(r"http(s)?://(?P<cdn>\w+\.)?afreeca(tv)?.com/(?P<username>\w+)(/\d+)?")

_channel_schema = validate.Schema(
    {
        "CHANNEL": {
            "RESULT": validate.transform(int),
            "BROAD_INFOS": [{
                "list": [{
                    "nBroadNo": validate.text
                }]
            }]
        }
    },
    validate.get("CHANNEL")
)
_stream_schema = validate.Schema(
    {
        validate.optional("view_url"): validate.url(
            scheme=validate.any("rtmp", "http")
        )
    }
)

class AfreecaTV(Plugin):
    @classmethod
    def can_handle_url(self, url):
        return _url_re.match(url)

    @classmethod
    def stream_weight(cls, key):
        weight = QUALITY_WEIGHTS.get(key)
        if weight:
            return weight, "afreeca"

        return Plugin.stream_weight(key)

    def _get_channel_info(self, username):
        headers = {
            "Referer": self.url
        }
        params = {
            "uid": username
        }
        res = http.get(CHANNEL_INFO_URL, params=params, headers=headers)

        return http.json(res, schema=_channel_schema)

    def _get_hls_key(self, broadcast, username, quality):
        headers = {
            "Referer": self.url
        }

        data = {
            "bid": username,
            "bno": broadcast,
            "player_type": "html5",
            "pwd": "",
            "quality": quality,
            "type": "pwd"
        }
        res = http.post(HLS_KEY_URL, data=data, headers=headers)
        return http.json(res)

    def _get_stream_info(self, broadcast, quality, cdn):
        params={
            "return_type": cdn,
            "use_cors": "true",
            "cors_origin_url": "play.afreecatv.com",
            "broad_key": "{broadcast}-flash-{quality}-hls".format(**locals())
        }
        res = http.get(STREAM_INFO_URLS, params=params)
        return http.json(res, schema=_stream_schema)

    def _get_hls_stream(self, broadcast, username, quality, cdn):
        keyjson = self._get_hls_key(broadcast, username, quality)
        if keyjson["CHANNEL"]["RESULT"] != "1":
            return
        key = keyjson["CHANNEL"]["AID"]

        info = self._get_stream_info(broadcast, quality, cdn)
        if "view_url" in info:
            return HLSStream(self.session, info["view_url"], params=dict(aid=key))

    def _get_streams(self):
        match = _url_re.match(self.url)
        username = match.group("username")
        tcdn = match.group("cdn")
        if tcdn=="aws.":
            cdn="aws_cf"
        else:
            cdn="gs_cdn"

        channel = self._get_channel_info(username)
        if channel["RESULT"] != CHANNEL_RESULT_OK:
            return

        broadcast = channel["BROAD_INFOS"][0]["list"][0]["nBroadNo"]
        if not broadcast:
            return

        for skey in CDN_SITES:
            for qkey in QUALITYS:
                hls_stream = self._get_hls_stream(broadcast, username, qkey, CDN_SITES.get(skey))
                if hls_stream:
                    yield skey+"_"+qkey, hls_stream

__plugin__ = AfreecaTV
cdrage commented 7 years ago

Please use https://github.com/streamlink/streamlink

@chrippa has abandoned the project and we're unable to contact him through GitHub / email / his work or twitter

1world2share commented 7 years ago

thank you @trocknet