Однажды у меня родился в голове вопрос о том, как бы выглядело видео, если посмотреть на него «сбоку». То есть, если сложить все кадры видео в стопку один за другим, потом разрезать эту стопку на части вдоль оси времени, получив тем самым кадры для нового видео:
Но в интернете я не нашёл ответа. Наконец, дошли руки проделать такой эксперимент.
Ширина нового видео в таком случае равняется количеству кадров исходного, а количество кадров нового видео — ширине исходного. Я прикинул, что лучше ограничиться небольшим форматом видео (640х360) и отрезком в 640 кадров, чтобы итоговое видео получилось не утомительным по времени и достаточным, для наблюдения эффекта. Экспортировал кадры из VirtualDub в png, набросал программку для Node.js (что первое под руку попалось), обработал, собрал новые кадры обратно в видео. И вот, что получилось.
Исходное видео:
Вид сбоку:
Результат оказался интереснее, чем я ожидал. Я думал меньше распознаваемых деталей будет. Просмотрел несколько раз, чтобы разглядеть каждую сцену, потом решил взглянуть «сверху».
Вид сверху:
Вид сверху получился квадратным, более коротким (360 кадров) и менее забавным. Учитывая полученный опыт, я попытался подобрать сцену, которая смотрелась бы интереснее — с плавно перемещающимися относительно камеры персонажами в полный рост или лицо крупным планом.
Исходное видео:
Вид сбоку:
var FRAME_WIDTH = 688;
var FRAME_HEIGHT = 384;
var FRAMES_COUNT = FRAME_WIDTH;
var fs = require('fs');
var PNG = require('node-png').PNG;
function makeFileName(i, prefix) {
prefix = prefix || "srcv/";
return prefix + ("00" + i).substr(-3) + ".png";
}
function createFrame(dstFrameIdx) {
var dstFrame = new PNG({
width: FRAMES_COUNT,
height: FRAME_HEIGHT
});
var done = 0;
for (var i = 0; i < FRAME_WIDTH; i++) {
var srcFrameData = fs.readFileSync(makeFileName(i));
var srcFrame = new PNG({filterType: 4});
srcFrame.on("parsed", (function (srcFrameIdx) {
return function () {
for (var p = 0; p < FRAME_HEIGHT; p++) {
var srcIdx = (FRAME_WIDTH * p + (FRAME_WIDTH - dstFrameIdx - 1)) << 2;
var dstIdx = (FRAMES_COUNT * p + srcFrameIdx) << 2;
dstFrame.data[dstIdx] = this.data[srcIdx];
dstFrame.data[dstIdx + 1] = this.data[srcIdx + 1];
dstFrame.data[dstIdx + 2] = this.data[srcIdx + 2];
dstFrame.data[dstIdx + 3] = this.data[srcIdx + 3];
}
if (++done == FRAMES_COUNT) {
dstFrame.pack().pipe(fs.createWriteStream(makeFileName(dstFrameIdx, "dstv/")))
.on("finish", function () {
console.log("done " + dstFrameIdx);
dstFrameIdx++;
if (dstFrameIdx < FRAMES_COUNT) {
createFrame(dstFrameIdx);
}
});
}
};
})(i));
srcFrame.write(srcFrameData);
}
}
createFrame(+process.argv[2]);
Не старался и не думал об оптимизации, хотел скорее получить хоть какой-то результат. После обработки первых кадров понял, что ждать не много (минут 10-15), если запустить сразу несколько процессов, и успокоился.
YouTube вроде попортил качество видео немного, поэтому прилагаю оригинальные файлы на всякий случай. Кстати, видео «с другого направления» сжимаются хуже при тех же настройках кодека.
Если кто-то уже делал нечто подобное или встречал, или есть другие идеи по необычному представлению видео или звука, делитесь в комментариях. Спасибо за внимание :)
Автор: brdsoft