-
-
Save datguypiko/45c2f87b408646229ffcaaee452de9c9 to your computer and use it in GitHub Desktop.
VLC playlist parser for Twitch.tv - https://addons.videolan.org/p/1167220/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
Twitch.tv extension v0.0.2 by Stefan Sundin | |
https://gist.github.com/stefansundin/c200324149bb00001fef5a252a120fc2 | |
The only thing that this extension does is to act as a helper to seek to the | |
correct time when you open a twitch.tv url that contains a timestamp. | |
You must have the playlist parser installed as well! | |
Usage: | |
1. Install the playlist parser: https://addons.videolan.org/p/1167220/ | |
2. Install this file in the lua/extensions/ directory: | |
- On Windows: %APPDATA%/vlc/lua/extensions/ | |
- On Mac: $HOME/Library/Application Support/org.videolan.vlc/lua/extensions/ | |
- On Linux: ~/.local/share/vlc/lua/extensions/ | |
- On Linux (snap package): ~/snap/vlc/current/.local/share/vlc/lua/extensions/ | |
To install the addon for all users, put the file here instead: | |
- On Windows: C:/Program Files/VideoLAN/VLC/lua/extensions/ | |
- On Mac: /Applications/VLC.app/Contents/MacOS/share/lua/extensions/ | |
- On Linux: /usr/lib/vlc/lua/extensions/ | |
- On Linux (snap package): /snap/vlc/current/usr/lib/vlc/lua/extensions/ | |
3. Open VLC and activate the extension via the menu. | |
NOTE: You must do this every time you restart VLC, as far as I know there is | |
no way for the extension to activate itself. :( | |
There is no feedback indicating that the extension was activated. | |
4. Open a twitch.tv url with a timestamp using "Open Network Stream..." | |
Download and install with one command on Mac: | |
curl -o "$HOME/Library/Application Support/org.videolan.vlc/lua/extensions/twitch-extension.lua" https://gist.githubusercontent.com/stefansundin/c200324149bb00001fef5a252a120fc2/raw/twitch-extension.lua | |
Download and install with one command on Linux: | |
curl -o ~/.local/share/vlc/lua/extensions/twitch-extension.lua https://gist.githubusercontent.com/stefansundin/c200324149bb00001fef5a252a120fc2/raw/twitch-extension.lua | |
Example url: | |
https://www.twitch.tv/gamesdonequick/video/113837699?t=23m56s | |
https://www.twitch.tv/videos/113837699?t=23m56s | |
https://player.twitch.tv/?video=v113837699&time=23m56s | |
Changelog: | |
- v0.0.2: Support new go.twitch.tv urls (beta site). | |
- v0.0.1: First version of extension. | |
--]] | |
require 'common' | |
function descriptor() | |
return { | |
title = "Twitch.tv Extension v0.0.2", | |
shortdesc = "Twitch.tv Extension v0.0.2", | |
version = "v0.0.2", | |
author = "Stefan Sundin", | |
url = "https://gist.github.com/stefansundin/c200324149bb00001fef5a252a120fc2", | |
description = "This extension is needed to support jumping to a twitch.tv timestamp indicated by ?t= in the URL. VLC extensions must be activated each time VLC is run. This is unfortunate and I have not found any workaround.", | |
capabilities = { "input-listener" } | |
} | |
end | |
function activate() | |
check_meta() | |
end | |
function input_changed() | |
check_meta() | |
end | |
-- The extension does not work if I name this string.starts, so weird.. | |
function stringstarts(haystack, needle) | |
return string.sub(haystack, 1, string.len(needle)) == needle | |
end | |
function check_meta() | |
if vlc.input.is_playing() then | |
local item = vlc.item or vlc.input.item() | |
if item then | |
local meta = item:metas() | |
if meta and meta["url"] then | |
vlc.msg.info("Trying to parse t from: "..meta["url"]) | |
if (stringstarts(meta["url"], "https://www.twitch.tv/") or stringstarts(meta["url"], "https://go.twitch.tv/") or stringstarts(meta["url"], "https://player.twitch.tv/")) and (string.find(meta["url"], "[?&]t=") or string.find(meta["url"], "[?&]time=")) then | |
local t = string.match(meta["url"], "[?&]t=([^&#]+)") or string.match(meta["url"], "[?&]time=([^&#]+)") | |
vlc.msg.info("t="..t) | |
local start = 0 | |
local h = string.match(t, "(%d+)h") | |
if h then | |
-- vlc.msg.info("h: "..h) | |
start = start + tonumber(h)*3600 | |
end | |
local m = string.match(t, "(%d+)m") | |
if m then | |
-- vlc.msg.info("m: "..m) | |
start = start + tonumber(m)*60 | |
end | |
local s = string.match(t, "(%d+)s") | |
if s then | |
-- vlc.msg.info("s: "..s) | |
start = start + tonumber(s) | |
end | |
vlc.msg.info("Seeking to: "..start) | |
common.seek(start) | |
end | |
end | |
end | |
return true | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
Twitch.tv playlist parser v0.3.0 by Stefan Sundin | |
https://gist.github.com/stefansundin/c200324149bb00001fef5a252a120fc2 | |
https://www.opencode.net/stefansundin/twitch.lua | |
https://addons.videolan.org/p/1167220/ | |
Once installed, you can open a twitch.tv url using "Open Network Stream..." | |
Features: | |
- Load a channel and watch live: https://www.twitch.tv/speedgaming | |
- Load an archived video: https://www.twitch.tv/videos/113837699 | |
Installation: | |
Put the file in the lua/playlist/ directory: | |
- On Windows: %APPDATA%/vlc/lua/playlist/ | |
- On Mac: $HOME/Library/Application Support/org.videolan.vlc/lua/playlist/ | |
- On Linux: ~/.local/share/vlc/lua/playlist/ | |
- On Linux (snap package): ~/snap/vlc/current/.local/share/vlc/lua/playlist/ | |
To install the addon for all users, put the file here instead: | |
- On Windows: C:/Program Files/VideoLAN/VLC/lua/playlist/ | |
- On Mac: /Applications/VLC.app/Contents/MacOS/share/lua/playlist/ | |
- On Linux: /usr/lib/vlc/lua/playlist/ | |
- On Linux (snap package): /snap/vlc/current/usr/lib/vlc/lua/playlist/ | |
On Linux, you can download and install with the following command: | |
mkdir -p ~/.local/share/vlc/lua/playlist/; curl -o ~/.local/share/vlc/lua/playlist/twitch.lua https://gist.githubusercontent.com/stefansundin/c200324149bb00001fef5a252a120fc2/raw/twitch.lua | |
On Mac, you can download and install with the following command: | |
mkdir -p "$HOME/Library/Application Support/org.videolan.vlc/lua/playlist/"; curl -o "$HOME/Library/Application Support/org.videolan.vlc/lua/playlist/twitch.lua" https://gist.githubusercontent.com/stefansundin/c200324149bb00001fef5a252a120fc2/raw/twitch.lua | |
Changelog: | |
- v0.3.0: Twitch finally completely shut down their old API. Because VLC scripts can't easily make POST requests it currently requires a proxy to work. To simplify things I removed all features besides loading a live channel and archived videos. I could potentially add back some of the features in the future but I am unsure if I have the will to do it. | |
- v0.2.3: Fix loading the list of a channel's old videos. Remove support for clips as it is broken and not easy to fix. | |
- v0.2.2: Fix 1080p on archived videos. Add audio only stream. | |
- v0.2.1: Skip live videos when loading /<channel>/videos. | |
- v0.2.0: Support new URLs. Most things seem to be working again. | |
- v0.1.3: Minor fix that prevented me from running this on Ubuntu 18.04 (snap package). | |
- v0.1.2: Support for /directory/game/<name>/videos/<type>. | |
- v0.1.1: Support for /<channel>/clips, /directory/game/<name>/clips. Add ability to load the next page. | |
- v0.1.0: Rewrote almost the whole thing. Support for /communities/<name>, /directory/game/<name>, /<channel>/videos/, collections. | |
- v0.0.6: Support new go.twitch.tv urls (beta site). | |
- v0.0.5: Fix a couple of minor issues. | |
- v0.0.4: Support new twitch.tv/videos/ urls. | |
- v0.0.3: Support for Twitch Clips. | |
- v0.0.2: You can now pick the stream quality you want. The twitch URL will expand to multiple playlist items. | |
Handy references: | |
https://github.com/videolan/vlc/blob/master/share/lua/README.txt | |
https://github.com/videolan/vlc/blob/7f6786ab6c8fb624726a63f07d79c23892827dfb/share/lua/playlist/appletrailers.lua#L34 | |
--]] | |
function parse_json(str) | |
vlc.msg.dbg("Parsing JSON: " .. str) | |
local json = require("dkjson") | |
return json.decode(str) | |
end | |
function get_json(url) | |
vlc.msg.info("Getting JSON from " .. url) | |
local stream = vlc.stream(url) | |
local data = "" | |
local line = "" | |
if not stream then return false end | |
while true do | |
line = stream:readline() | |
if not line then break end | |
data = data .. line | |
end | |
return parse_json(data) | |
end | |
function get_streams(url, title) | |
vlc.msg.info("Getting items from " .. url) | |
-- #EXTM3U | |
-- #EXT-X-TWITCH-INFO:NODE="video-edge-c9010c.lax03",MANIFEST-NODE-TYPE="legacy",MANIFEST-NODE="video-edge-c9010c.lax03",SUPPRESS="false",SERVER-TIME="1483827093.91",USER-IP="76.94.205.190",SERVING-ID="4529b3c0570a46c8b3ed902f68b8368f",CLUSTER="lax03",ABS="false",BROADCAST-ID="24170411392",STREAM-TIME="5819.9121151",MANIFEST-CLUSTER="lax03" | |
-- #EXT-X-MEDIA:TYPE=VIDEO,GROUP-ID="chunked",NAME="Source",AUTOSELECT=YES,DEFAULT=YES | |
-- #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2838000,RESOLUTION=1280x720,VIDEO="chunked" | |
local stream = vlc.stream(url) | |
if not stream then return false end | |
local items = {} | |
local name = "error" | |
-- local resolution = "error" | |
while true do | |
local line = stream:readline() | |
if not line then break end | |
if string.find(line, "^#.*NAME=") then | |
name = string.match(line, "NAME=\"?([a-zA-Z0-9_ \\(\\)]+)\"?") | |
if name == "1080p (source)" then | |
name = "1080p" | |
elseif name == "audio_only" then | |
name = "Audio Only" | |
end | |
-- elseif string.find(line, "^#.*RESOLUTION=") then | |
-- resolution = string.match(line, "RESOLUTION=\"?([0-9x]+)\"?") | |
elseif string.find(line, "^http") then | |
table.insert(items, { path=line, name=title.." ["..name.."]" }) | |
-- Uncomment the line below to only have the first stream appear (i.e. best quality) | |
-- break | |
end | |
end | |
return items | |
end | |
function url_encode(str) | |
str = string.gsub(str, "\n", "\r\n") | |
str = string.gsub(str, "([^%w %-%_%.%~])", function(c) return string.format("%%%02X", string.byte(c)) end) | |
str = string.gsub(str, " ", "+") | |
return str | |
end | |
function string.starts(haystack, needle) | |
return string.sub(haystack, 1, string.len(needle)) == needle | |
end | |
function probe() | |
return (vlc.access == "http" or vlc.access == "https") and (string.starts(vlc.path, "www.twitch.tv/") or string.starts(vlc.path, "go.twitch.tv/") or string.starts(vlc.path, "player.twitch.tv/")) | |
end | |
function parse() | |
local proxy_host = "https://vppp.fly.dev" | |
if string.find(vlc.path,"/video/") or string.find(vlc.path,"twitch.tv/videos/") or string.find(vlc.path,"video=") then | |
-- https://www.twitch.tv/gamesdonequick/video/113837699 | |
-- https://www.twitch.tv/videos/113837699 (legacy url) | |
-- https://www.twitch.tv/gamesdonequick/v/113837699 (legacy url, will redirect to /videos/ so we don't need to check for it) | |
-- https://player.twitch.tv/?video=v113837699&parent=example.com ("v" is optional) | |
local video_id = string.match(vlc.path, "/video/(%d+)") or string.match(vlc.path, "/videos/(%d+)") or string.match(vlc.path, "video=v?(%d+)") | |
vlc.msg.info(string.format("video_id: %s", video_id)) | |
local data = get_json(proxy_host.."/api/vods/"..video_id.."/access_token") | |
local url = "http://usher.twitch.tv/vod/"..video_id.."?player=twitchweb&nauthsig="..data["sig"].."&nauth="..url_encode(data["token"]).."&allow_audio_only=true&allow_source=true" | |
return get_streams(url, "Twitch Video: "..video_id) | |
else | |
-- https://www.twitch.tv/speedgaming | |
local channel = string.match(vlc.path, "twitch.tv/([^/?#]+)") | |
if channel == "directory" or channel == "recaps" then | |
-- https://www.twitch.tv/directory/game/Perfect%20Dark | |
-- https://www.twitch.tv/recaps/annual | |
return { { path="", name="Unsupported URL" } } | |
end | |
vlc.msg.info(string.format("channel: %s", channel)) | |
local data = get_json(proxy_host.."/api/channels/"..channel.."/access_token") | |
local url = "http://usher.ttvnw.net/api/channel/hls/"..channel..".m3u8?player=twitchweb&token="..url_encode(data["token"]).."&sig="..data["sig"].."&allow_audio_only=true&allow_source=true&allow_spectre=true" | |
return get_streams(url, "Twitch Channel: "..channel) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
URL=$(curl -sL https://www.twitch.tv/ | grep -oE 'https://static.twitchcdn.net/assets/core-[a-z0-9]+.js') | |
curl -sL "$URL" | grep -oE '"[a-z0-9]{30}"' | |
# old: | |
# find the client_id that is used on twitch.tv | |
# curl -sL https://web-cdn.ttvnw.net/global.js | grep -oP '"[a-z0-9]{31}"' | |
# on mac: | |
# curl -sL https://web-cdn.ttvnw.net/global.js | grep -oE '"[a-z0-9]{31}"' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment