-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
plugins.douyin: new plugin #6059
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
Conversation
For info: plugins should be accompanied with a test. See: https://github.com/streamlink/streamlink/tree/master/tests/plugins |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
New plugins will require a plugin request issue first, with all the required details:
https://github.com/streamlink/streamlink/issues/new/choose
cookies are necessary
Merging a new plugin where custom HTTP headers like cookies are required won't happen. A plugin will have to work out of the box, and if authentication is required, then this need to be implemented using plugin arguments. From a quick test in my web browser though, there's no authentication required.
cookies are not necessary, here is my own use for your reference """
$description douyin
$url live.douyin.com
$type live
"""
import json
import logging
import re
import uuid
from streamlink.plugin import Plugin, pluginmatcher
from streamlink.plugin.api import validate
from streamlink.stream.hls import HLSStream
from streamlink.stream.http import HTTPStream
log = logging.getLogger(__name__)
@pluginmatcher(re.compile(
r"https?://live\.douyin\.com/(?P<channel>[^/]+)",
))
class Douyin(Plugin):
def _get_streams(self):
channel = self.match.group("channel")
uuid21 = uuid.uuid4().hex[:21]
self.session.http.headers.update({"Cookie": "__ac_nonce=" + uuid21})
res = self.session.http.get(self.url)
try:
data = re.findall(r'self.__pace_f.push\(\[\d,("[a-z]:.+?")\]\)</script>', res.text)[-1]
except:
return
data = json.loads(data)
m = re.search(r'(\[.+\])', data)
data = json.loads(m.groups()[0])[-1]
try:
video_info = data['state']['roomStore']['roomInfo'].get('room')
except:
return
try:
if video_info['status'] != 2:
return
except:
return
try:
video_info_h264 = data['state']['streamStore']['streamData']['H264_streamData']['stream']['origin'].get('main')
flv_url = video_info_h264['flv']
hls_url = video_info_h264['hls']
except:
flv_url = video_info['stream_url']['flv_pull_url']['FULL_HD1']
hls_url = video_info['stream_url']['hls_pull_url_map']['FULL_HD1']
yield "live", HTTPStream(self.session, flv_url)
s = HLSStream.parse_variant_playlist(self.session, hls_url)
if not s:
yield "live", HLSStream(self.session, hls_url)
elif len(s) == 1:
yield "live", next(iter(s.values()))
else:
yield from s.items()
__plugin__ = Douyin |
cookies are not required now |
Thank you very much. I successfully ran it using your method. I have refactored my code using your method. |
@v2wy, instead of reviewing and annotating changes, I decided to fix any left over code issues myself and force-push onto your PR branch. The commit author data is left intact. Hope that's okay...
As commented in the plugin code, HLS streams are available, but using those would cause an unnecessary delay when fetching the streams, because there are multivariant playlists for each quality which consist of only a single media playlist, so each multivariant playlist would need to be queried. That's not worth it, despite progressive HTTP streams being pretty bad for live streaming. Live channel:
Offline channel:
Non-existing channel:
|
Co-Authored-By: bastimeyer <mail@bastimeyer.de>
Thank you very much for your review and modifications. I have learned a lot from your comments. The code written earlier was somewhat casual. I will submit a PR following the guidelines. |
Resolves #6062
cookies are necessary
test url : https://live.douyin.com/774321108336
python.exe -m src.streamlink_cli -j https://live.douyin.com/774321108336 --http-cookie __ac_nonce=xxx --http-cookie __ac_signature=xxx --http-cookie sessionid=xxx