Skip to content

Instantly share code, notes, and snippets.

@jamesWalker55
Forked from ishitatsuyuki/autoeditor.js
Last active April 6, 2022 22:25
Show Gist options
  • Save jamesWalker55/bd9ce5abea17f29a9bc3b9ee032f04be to your computer and use it in GitHub Desktop.
Save jamesWalker55/bd9ce5abea17f29a9bc3b9ee032f04be to your computer and use it in GitHub Desktop.
This script loads a JSON file produced by auto-editor, and skips regions of the video based on the JSON output. Place this script in your mpv scripts folder.
var timeObserver;
/** seek playback to the given second */
function seek_to(time) {
mp.set_property_number("time-pos", time);
}
function get_json_path() {
var video_path = mp.get_property("path");
return video_path.replace(/\.[^.]+$/, ".json");
}
function read_json(path) {
try {
return JSON.parse(mp.utils.read_file(path));
} catch (e) {
return null;
}
}
/** Return the list of ranges that should be viewed */
function get_view_ranges(autoeditor_json_path) {
var content = read_json(autoeditor_json_path);
if (content === null) {
return null;
}
return content["chunks"].filter(function (c) { return c[2] == 1; });
}
/**
* Given a starting frame, return a code and an optional range.
*
* - If we are outside a range, return [0, the next range].
* - If we are inside a range, then return [1, the current range].
* - If we are outside a range and there is no next range, return [2, null].
*/
function get_range_info(ranges, now) {
var min = 0;
var max = ranges.length - 1;
var idx = Math.round(max / 2);
// perform binary search
while (true) {
if (max < min) {
if (min == ranges.length) return [2, null];
return [0, ranges[min]];
}
var range_start = ranges[idx][0];
var range_end = ranges[idx][1];
if (range_start > now) {
// this range starts later than now
max = idx - 1;
idx = Math.round((min + max) / 2);
} else if (range_end < now) {
// this range ends earlier than now
min = idx + 1;
idx = Math.round((min + max) / 2);
} else {
// we are inside this range
return [1, null];
}
}
}
function load() {
unload(); // Unload previous callbacks
var json_path = get_json_path();
var view_ranges = get_view_ranges(json_path);
if (view_ranges === null) {
return;
}
if (view_ranges.length == 0) {
return;
}
mp.osd_message(
"auto-editor: Loaded " + view_ranges.length + " ranges"
);
timeObserver = function (_, seconds) {
var current_fps = mp.get_property_number("estimated-vf-fps");
if (current_fps == undefined) return;
var current_frame = Math.round(seconds * current_fps);
var info = get_range_info(view_ranges, current_frame);
if (info[0] === 0) {
// seek to next range
seek_to(info[1][0] / current_fps);
} else if (info[0] == 1) {
// we are in a normal range, do nothing
return;
} else if (info[0] == 2) {
// end of video, move on to next video
mp.command("playlist-next");
}
};
mp.observe_property("time-pos", "number", timeObserver);
}
function unload() {
if (timeObserver != null) {
mp.unobserve_property(timeObserver);
timeObserver = null;
}
}
mp.register_event("start-file", load);
mp.register_event("end-file", unload);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment