Skip to content

Instantly share code, notes, and snippets.

@aixxe
Last active February 6, 2017 15:52
Show Gist options
  • Save aixxe/c2b2cace9490b151af6ef976e04f9d94 to your computer and use it in GitHub Desktop.
Save aixxe/c2b2cace9490b151af6ef976e04f9d94 to your computer and use it in GitHub Desktop.
Hastily written video splitter thing I previously used for lody's past broadcasts.
#!/bin/node
const fs = require("fs");
const path = require("path");
const async = require("async");
const mkdirp = require("mkdirp");
const minimist = require("minimist");
const child_process = require("child_process");
var argv = minimist(process.argv.slice(2));
Number.prototype.padLeft = function(n) {
return Array(n - String(this).length + 1).join("0") + this;
}
function toSeconds(time) {
var segments = time.split(':');
return (segments[0] * 3600 + segments[1] * 60 + segments[2] * 1);
}
function secondsToTime(secs) {
var hours = Math.floor(secs / (60 * 60));
var divisor_for_minutes = secs % (60 * 60);
var minutes = Math.floor(divisor_for_minutes / 60);
var divisor_for_seconds = divisor_for_minutes % 60;
var seconds = Math.ceil(divisor_for_seconds);
return hours.padLeft(2) + ":" + minutes.padLeft(2) + ":" + seconds.padLeft(2);
}
// read configuration file with split timings
const config = JSON.parse(fs.readFileSync(argv.t, "utf8"));
// create processing queue.
var queue = async.queue(function(video, callback) {
// calculate the starting timestamp of this video.
var time = config.timestamp + toSeconds(video.start);
// calculate the duration in seconds of this video.
var duration = toSeconds(video.end) - toSeconds(video.start);
var duration_str = secondsToTime(duration);
// output additional information for the database.
var start_time_str = secondsToTime(toSeconds(video.start));
var end_time_str = secondsToTime(toSeconds(video.end));
// create the output directory.
var output_folder = "./output/stream-" + time;
var output_playlist = path.resolve(output_folder, "index.m3u8");
var output_files = path.resolve(output_folder, "%d.ts");
mkdirp(output_folder);
// split the video.
child_process.exec("ffmpeg -i \"" + path.resolve(argv.i) + "\" -c copy -bsf:v h264_mp4toannexb -ss " + start_time_str + " -t " + duration_str + " -segment_time 4 -f segment -segment_list \"" + output_playlist + "\" \"" + output_files + "\"", (error, stdout, stderr) => {
if (error) {
callback(true);
}
// generate thumbnail
fs.readdir(output_folder, (error, files) => {
if (error)
return false;
var segments = files.filter(value => value.endsWith(".ts"));
var segment = output_folder + path.sep + segments[Math.floor(Math.random() * segments.length)];
child_process.exec("ffmpeg -y -i \"" + segment + "\" -vframes 1 -filter:v scale=\"min(640\\, iw):-1\" " + time + ".jpg", (error, stdout, stderr) => {
console.log(time + " - " + start_time_str + " -> " + end_time_str + " [" + duration_str + "] - " + duration + " seconds");
callback(false);
});
});
});
}, 2);
// calculate durations and start timestamps
for (var i = 0; i < config.videos.length; i++) {
queue.push(config.videos[i]);
}
{
"timestamp": 1478643356,
"videos": [
{"start": "00:01:36", "end": "00:12:26"},
{"start": "00:15:32", "end": "00:22:58"},
{"start": "00:22:58", "end": "00:27:01"},
{"start": "00:27:30", "end": "00:34:45"},
{"start": "00:35:38", "end": "00:37:59"},
{"start": "00:38:10", "end": "00:41:14"},
{"start": "00:41:50", "end": "00:51:00"},
{"start": "00:51:10", "end": "00:57:21"},
{"start": "00:57:20", "end": "01:05:50"},
{"start": "01:05:51", "end": "01:15:16"}
]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment