-
-
Save stefansundin/c200324149bb00001fef5a252a120fc2 to your computer and use it in GitHub Desktop.
--[[ | |
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 |
--[[ | |
Twitch.tv playlist parser v0.3.1 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 | |
- Load a clip: https://clips.twitch.tv/AmazonianKnottyLapwingSwiftRage | |
This playlist parser utilizes a proxy since v0.3.0 since Twitch completely shut down their old API. | |
VLC can't make POST requests so there isn't another way to work around the problem. | |
For information about the proxy please go to https://github.com/stefansundin/media-resolver | |
You can run the proxy on your own computer but you'll have to edit the proxy_host variable below. | |
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.1: Added back support for clips. | |
- 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 | |
--]] | |
-- Set this variable to true to only add the first stream: | |
local only_add_one_stream = false | |
-- You can change the order of the streams using this variable: | |
local preferred_streams = {} | |
-- Examples: | |
-- local preferred_streams = { "1080p", "720p" } | |
-- local preferred_streams = { "360p", "160p", "720p60", "720p" } | |
-- local preferred_streams = { "Audio Only" } | |
-- | |
-- Technical note: | |
-- The sort algorithm is not stable. This means that streams not listed here may become jumbled by the sorting (the sorting only happens if this list has entries in it). | |
-- You can modify this variable to only include certain streams: | |
local allowed_streams = {} | |
-- Examples: | |
-- local allowed_streams = { "1080p" } | |
-- local allowed_streams = { "360p", "720p" } | |
-- local allowed_streams = { "360p" } | |
-- It does a substring match, so you can use "1080p" to allow both "1080p" and "1080p60". | |
-- You can modify this variable to skip certain streams: | |
local skipped_streams = {} | |
-- Examples: | |
-- local skipped_streams = { "1080p", "Audio Only" } | |
-- It does a substring match, so you can use "1080p" to block both "1080p" and "1080p60". | |
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(item) | |
vlc.msg.info("Getting streams from " .. item.path) | |
-- #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(item.path) | |
if not stream then | |
return { { path="", name="Error fetching streams" } } | |
end | |
local items = {} | |
local name = "error" | |
local add_stream = true | |
-- 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 == "audio_only" then | |
name = "Audio Only" | |
end | |
add_stream = true | |
if #allowed_streams > 0 then | |
add_stream = false | |
for _, stream in ipairs(allowed_streams) do | |
if string.find(name, stream) then | |
add_stream = true | |
end | |
end | |
end | |
for _, stream in ipairs(skipped_streams) do | |
if string.find(name, stream) then | |
add_stream = false | |
end | |
end | |
-- elseif string.find(line, "^#.*RESOLUTION=") then | |
-- resolution = string.match(line, "RESOLUTION=\"?([0-9x]+)\"?") | |
elseif string.find(line, "^http") and add_stream then | |
-- Make a copy and overwrite some attributes | |
local new_item = {} | |
for k, v in pairs(item) do | |
new_item[k] = v | |
end | |
new_item.path = line | |
new_item.name = item.name.." ["..name.."]" | |
table.insert(items, new_item) | |
if only_add_one_stream then | |
break | |
end | |
end | |
end | |
if #preferred_streams > 0 then | |
table.sort(items, sort_streams) | |
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 proxy_resolve(url) | |
-- Don't just copy this URL to your own app without understanding it. | |
-- Do NOT use the "v=1" query parameter if you use this in another app! | |
local proxy_host = "https://media-resolver.fly.dev" | |
-- If you are running your own media resolver then comment out the line above and uncomment the line below: | |
-- local proxy_host = "http://localhost:8080" | |
return proxy_host.."/resolve?v=1&output=json&url="..url_encode(url) | |
end | |
function string.starts(haystack, needle) | |
return string.sub(haystack, 1, string.len(needle)) == needle | |
end | |
function sort_streams(a, b) | |
local i = table.index(preferred_streams, a.name) | |
local j = table.index(preferred_streams, b.name) | |
if i == nil and j == nil then | |
return false | |
elseif i ~= nil and j == nil then | |
return true | |
elseif i == nil and j ~= nil then | |
return false | |
end | |
return i < j | |
end | |
function table.index(t, x) | |
for i, v in pairs(t) do | |
if string.find(x, v) then | |
return i | |
end | |
end | |
return nil | |
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/") or string.starts(vlc.path, "clips.twitch.tv/")) | |
end | |
function parse() | |
local url = vlc.access.."://"..vlc.path | |
local data = get_json(proxy_resolve(url)) | |
if data.error then | |
return { { path="", name="Error: "..data.error } } | |
end | |
local items = {} | |
for _, item in ipairs(data) do | |
if string.find(item.path, ".m3u8") then | |
-- We resolve m3u8 files into quality options here because we won't get a chance to do it later | |
for _, stream in ipairs(get_streams(item)) do | |
table.insert(items, stream) | |
end | |
else | |
table.insert(items, item) | |
end | |
end | |
return items | |
end |
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}"' |
Hello, how can I change the resolution? broadcast or video quality at 720p or 480p
@Khomchyk1992 I have pushed some updates to the script to allow the resolution to be picked more easily. I have NOT released this on addons.videolan.org yet, so for now please download the twitch.lua
file manually here.
You have to edit a few variables in the code. They are named only_add_one_stream
, preferred_streams
, allowed_streams
, and skipped_streams
. Hopefully they should let you do what you want.
Please write a comment here if they solve your problem, and if you have any feedback. Thanks.
@Khomchyk1992 I have pushed some updates to the script to allow the resolution to be picked more easily. I have NOT released this on addons.videolan.org yet, so for now please download the
twitch.lua
file manually here.You have to edit a few variables in the code. They are named
only_add_one_stream
,preferred_streams
,allowed_streams
, andskipped_streams
. Hopefully they should let you do what you want.Please write a comment here if they solve your problem, and if you have any feedback. Thanks.
Thank you very much, set your value, everything works.
Thanks. Works great.