-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: sponsor blocking in youtube videos
- Loading branch information
1 parent
3383530
commit ce744e3
Showing
2 changed files
with
148 additions
and
0 deletions.
There are no files selected for viewing
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
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
-- sponsorblock-minimal.lua | ||
-- source: https://codeberg.org/jouni/mpv_sponsorblock_minimal | ||
-- | ||
-- This script skips sponsored segments of YouTube videos | ||
-- using data from https://github.com/ajayyy/SponsorBlock | ||
|
||
local opt = require 'mp.options' | ||
local utils = require 'mp.utils' | ||
|
||
local ON = false | ||
local ranges = nil | ||
|
||
local options = { | ||
server = "https://sponsor.ajay.app/api/skipSegments", | ||
|
||
-- Categories to fetch and skip | ||
categories = '"sponsor"', | ||
|
||
-- Set this to "true" to use sha256HashPrefix instead of videoID | ||
hash = "" | ||
} | ||
|
||
opt.read_options(options) | ||
|
||
function get_ranges(youtube_id, url) | ||
local luacurl_available, cURL = pcall(require,'cURL') | ||
|
||
local res = nil | ||
if not(luacurl_available) then -- if Lua-cURL is not available on this system | ||
local sponsors = mp.command_native{ | ||
name = "subprocess", | ||
capture_stdout = true, | ||
playback_only = false, | ||
args = {"curl", "-L", "-s", "-g", url} | ||
} | ||
res = sponsors.stdout | ||
else -- otherwise use Lua-cURL (binding to libcurl) | ||
local buf={} | ||
local c = cURL.easy_init() | ||
c:setopt_followlocation(1) | ||
c:setopt_url(url) | ||
c:setopt_writefunction(function(chunk) table.insert(buf,chunk); return true; end) | ||
c:perform() | ||
res = table.concat(buf) | ||
end | ||
|
||
if res then | ||
local json = utils.parse_json(res) | ||
if type(json) == "table" then | ||
if options.hash == "true" then | ||
for _, i in pairs(json) do | ||
if i.videoID == youtube_id then | ||
return i.segments | ||
end | ||
end | ||
else | ||
return json | ||
end | ||
end | ||
end | ||
|
||
return nil | ||
end | ||
|
||
function skip_ads(name,pos) | ||
if pos then | ||
for _, i in pairs(ranges) do | ||
v = i.segment[2] | ||
if i.segment[1] <= pos and v > pos then | ||
--this message may sometimes be wrong | ||
--it only seems to be a visual thing though | ||
mp.osd_message(("[sponsorblock] skipping forward %ds"):format(math.floor(v-mp.get_property("time-pos")))) | ||
--need to do the +0.01 otherwise mpv will start spamming skip sometimes | ||
--example: https://www.youtube.com/watch?v=4ypMJzeNooo | ||
mp.set_property("time-pos",v+0.01) | ||
return | ||
end | ||
end | ||
end | ||
end | ||
|
||
function file_loaded() | ||
local video_path = mp.get_property("path", "") | ||
local video_referer = string.match(mp.get_property("http-header-fields", ""), "Referer:([^,]+)") or "" | ||
|
||
local urls = { | ||
"ytdl://youtu%.be/([%w-_]+).*", | ||
"ytdl://w?w?w?%.?youtube%.com/v/([%w-_]+).*", | ||
"https?://youtu%.be/([%w-_]+).*", | ||
"https?://w?w?w?%.?youtube%.com/v/([%w-_]+).*", | ||
"/watch.*[?&]v=([%w-_]+).*", | ||
"/embed/([%w-_]+).*", | ||
"^ytdl://([%w-_]+)$", | ||
"-([%w-_]+)%." | ||
} | ||
local youtube_id = nil | ||
local purl = mp.get_property("metadata/by-key/PURL", "") | ||
for i,url in ipairs(urls) do | ||
youtube_id = youtube_id or string.match(video_path, url) or string.match(video_referer, url) or string.match(purl, url) | ||
if youtube_id then break end | ||
end | ||
|
||
if not youtube_id or string.len(youtube_id) < 11 then return end | ||
youtube_id = string.sub(youtube_id, 1, 11) | ||
|
||
local url = "" | ||
if options.hash == "true" then | ||
local sha = mp.command_native{ | ||
name = "subprocess", | ||
capture_stdout = true, | ||
args = {"sha256sum"}, | ||
stdin_data = youtube_id | ||
} | ||
url = ("%s/%s?categories=[%s]"):format(options.server, string.sub(sha.stdout, 0, 4), options.categories) | ||
else | ||
url = ("%s?videoID=%s&categories=[%s]"):format(options.server, youtube_id, options.categories) | ||
end | ||
|
||
ranges = get_ranges(youtube_id, url) | ||
if ranges then | ||
ON = true | ||
mp.add_key_binding("b","sponsorblock",toggle) | ||
mp.observe_property("time-pos", "native", skip_ads) | ||
end | ||
end | ||
|
||
function end_file() | ||
if not ON then return end | ||
mp.unobserve_property(skip_ads) | ||
ranges = nil | ||
ON = false | ||
end | ||
|
||
function toggle() | ||
if ON then | ||
mp.unobserve_property(skip_ads) | ||
mp.osd_message("[sponsorblock] off") | ||
ON = false | ||
else | ||
mp.observe_property("time-pos", "native", skip_ads) | ||
mp.osd_message("[sponsorblock] on") | ||
ON = true | ||
end | ||
end | ||
|
||
mp.register_event("file-loaded", file_loaded) | ||
mp.register_event("end-file", end_file) |