Восстановить искаженное видео WebM, сгенерированное VirtualBox

Когда мне позвонил индийский отдел «Microsoft», я позволил им присоединиться к моей виртуальной машине VirtualBox и начал захват видео, чтобы узнать о них какие-либо подробности. При этом VirtualBox создает видеофайлы .webm.

Однако, когда я теперь воспроизвожу этот файл webm, я вижу, что он был искажен именно там, где я изменил разрешение виртуальной машины. Сессия длилась час (уф...), и в конце мне удалось помешать их тщетным попыткам взлома установить системный пароль на моем компьютере, и вместо этого я снова вошел в соединение, которое они затем прервали. Я думаю, что тогда я увидел какую-то полноэкранную среду панели инструментов - может быть, их? Может быть, есть очень полезная информация, это правда!

Искажение кажется, что это просто проблема с длиной строки развертки в видеопотоке. Хитрость здесь в том, что само видео все правильно в разрешении 1024x768, но полезная нагрузка представляет собой просто область 800x600 посередине (с черными рамками вокруг нее). Эта внутренняя область - то, что еще больше испортилось в видео. Черные границы остаются в порядке, так что это просто исходный поток данных VirtualBox для средней части, который сместился.

Кто-нибудь знает о какой-то процедуре или программном обеспечении, которое я мог бы использовать, чтобы попытаться исправить это видео? Я уже видел, что видеофайлы webm используют стандарт, основанный на Matroska, и используют кодирование EBML; Я уже пытался изменить некоторые значения заголовков в структуре EBML, чтобы подделать разрешение экрана (чтобы черные границы сместились, но средняя полезная нагрузка была в порядке), но это ни к чему не привело (каждые 5 секунд видео или что-то подобное имеют свой собственный блок заголовка, например хорошо).

Добавление:

Если быть точным: видео рендерилось в разрешении 1024x786 пикселей, а виртуальная машина работала в разрешении 800x600. Это приводит к жирной черной рамке, окружающей внутренний захваченный контент на протяжении всего видео. После того, как я увеличил размер окна виртуальной машины (скажем, до 1200х650 - точно не могу сказать), черная рамка осталась прежней по размеру, только внутреннее содержимое в ней искажается. С искаженным я имею в виду, что он выглядит так, как будто он отображает теперь более длинные строки развертки в 1200 пикселей и оборачивает их длиной 800 строк развертки, таким образом, каждая следующая реальная строка развертки смещается на разницу в горизонтальном размере, поскольку предыдущая строка завернута в нее. По крайней мере, так я думал изначально, но, глядя на это снова, у меня возникают сомнения и в этой теории.

Ну вообще непонятно :) Кадр закачал сюда: кадр мошеннического видеоа короткий фрагмент видео сюда: короткий фрагмент скам-видео (проблема возникает на середине фрагмента)

Но, если честно, я думаю, что лучше сдаться. Я начинаю подозревать, что единственное возможное исправление - это сделать пиксельный захват в старых кадрах и построить из этого новое видео, если это вообще исправление - т.е. слишком много усилий. Позор, однако, так как я действительно хотел бы просмотреть содержание в конце...

Решение:

Благодаря bukkojot я придумал следующее (ориентированное на Windows) приложение, которое помещается в середину командной строки ffmpeg, которую он дал; может кому пригодится? Обратите внимание, что «RGB24» в командной строке должно быть «rgb24» при использовании последней версии ffmpeg в Windows, что приводит к командной строке, которую я использовал для:

ffmpeg.exe -i scamvideo_problem.webm -f rawvideo -pix_fmt rgb24 pipe: | restorer.exe | ffmpeg -f rawvideo -pix_fmt rgb24 -s 1103x436 -i pipe: -vcodec libx264 resolvedvideo.avi

Видео получилось разборчивым (не считая изменения цвета), и все вовлеченные в него стороны были уведомлены (iTunes, gmail, TeamViewer и VICIdial).

Во всяком случае, это код C++, который я использовал:

#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <Windows.h>
using namespace std;

int main() {
    const size_t inLineSize = 1024 * 3;
    const size_t inFrameSize = 1024 * 768 * 3;
    const size_t outFrameSize = 1103 * 436 * 3;

    const size_t inPayloadLineSize = 800 * 3;
    const size_t inPayloadNumLines = 600;
    const size_t inPayloadFrameSize = inPayloadLineSize * inPayloadNumLines;
    const size_t inTopBorderNumLines = 84;
    const size_t inLeftBorderNumPixels = 112;
    const size_t inPayloadOffset = inLineSize * inTopBorderNumLines + inLeftBorderNumPixels * 3;

    const size_t outPadSize = outFrameSize - inPayloadFrameSize;

    _setmode(_fileno(stdin), _O_BINARY);
    _setmode(_fileno(stdout), _O_BINARY);

    char* inFrame = new char[inFrameSize];
    char* outPadding = new char[outPadSize];
    memset(outPadding, 0, outPadSize);
    while (!feof(stdin)) {
        size_t sizeLeft = inFrameSize;
        char* nextReadPos = inFrame;
        while (!feof(stdin) && sizeLeft > 0) {
            size_t bytesRead = fread(nextReadPos, 1, sizeLeft, stdin);
            sizeLeft -= bytesRead;
            nextReadPos += bytesRead;
            if (sizeLeft > 0) {
                Sleep(100);
            }
        }
        if (!feof(stdin)) {
            char* inPayloadPos = inFrame;
            inPayloadPos += inPayloadOffset;
            for (size_t inLineNr = 0; inLineNr < inPayloadNumLines; ++inLineNr, inPayloadPos += inLineSize) {
                fwrite(inPayloadPos, 1, inPayloadLineSize, stdout);
            }
            fwrite(outPadding, 1, outPadSize, stdout);
        }
    }
    return 0;
}
Под искаженным вы имеете в виду только размер или ошибки декодирования?
@Mulvya: это... я обновлю пост, чтобы дать больше деталей :)

Ответы (1)

После небольшой манипуляции... Видите ли...

введите описание изображения здесь

Самый простой способ для вас:

  1. Напишите очень простое приложение на C, которое будет читать 1024*768*3 байта и дополнять нулями до 1327*768*3 байта. Вам легко.

  2. Сбрасывать необработанные пиксели с помощью ffmpeg, передавать данные в ваше приложение, передавать данные обратно в ffmpeg

Что-то вроде:

ffmpeg -i scamvideo.avi -f rawvideo -pix_fmt RGB24 - | ./a.out | ffmpeg -f rawvideo -pix_fmt RGB24 -s 1327x768 -i - -vcodec libx264 newvideo.avi

Все остальные варианты на ваш вкус. Я думаю, вы поняли.

Яркость была выровнена, но не цветность, которая будет уменьшена вдвое.
@bukkojot: БОЛЬШОЕ СПАСИБО! Вы не представляете, как сильно я хотел восстановить это видео! Теперь о его выполнении :) Я действительно смогу это сделать, но сначала мне нужно найти немного времени ... все равно есть видео, так что оно никуда не денется.
@Mulvya: * цветность - если она достаточно разборчива, я счастлив в кемпинге :)
все равно начал работать над этим, но я думаю, что мое время не является ограничивающим фактором - это время работы :)
Эта задача очень легкая. Вам нужен час или два.
Я тоже так думал, но поскольку я работаю в Windows, это оказалось сложнее, чем предполагалось. Преобразование работает, но я не могу заставить ffmpeg правильно передать свое приложение. Пропуск каналов и запись через временные файлы также нецелесообразны для вывода RAW с такой частотой кадров в течение 1 часа :) Продолжение следует после этих выходных.
Обязательно используйте двоичный режим. Под окнами это очень важно. Используйте winapi для двоичного чтения/записи
@bukkojot: бинарный режим действительно был ключевым. И... я вернул видео! Ну, только верхние 3/4 кадров, так как это единственная часть, которая была забита во внутреннюю часть 800x600. Во всяком случае, они получили адрес электронной почты, который они пытались использовать для получения подарочных карт iTunes, а также рабочий стол, который перед ними (они используют веб-клиент VICIdial). Успех! Отправляйтесь в контакт с мошенничеством@itunes, мошенничеством@teamviewer, мошенничеством@VICIdial и, возможно, с местной полицией (но я думаю, что не буду заморачиваться с последним). Без вашего ответа я бы не справился!
И еще один комментарий для тех, кто пытается сделать то же самое: НЕ используйте Powershell - в нем вы можете использовать конвейеры, но у него есть неприятная привычка пытаться буферизовать весь вывод stdout из одного приложения, прежде чем передавать его в следующее... выиграл не работает в этом случае конечно. Мне пришлось немного подергать волосы, чтобы понять это...