Скрипт deshaking'а видео в HorizonHD v3.

На мини-коптере у меня стоит камера HorizonHD v3, которой я снимаю в 720p 60Hz (59.640 Hz). У нее есть интересная особенность - почему-то в каждой четверке кадров 3-й и 4-й кадры одинаковы. Может это особенность формата - там используется какой-то Apple’овый MOV. Из-за этого у Deskaker’а ломается алгоритм, думает что между 3 и 4 кадрами движения не было, а до этого было, и на выходе получается дергание и даже движение в другую сторону. 😃

Собственно скрпит и решает эту проблему, удалением каждого четвертого кадра (с помощью магии), вырезанием нужного участка (первый и последний фрейм задаются в параметрах) и выполнением deshaking’а с рендерингом в FFDshow для монтажа (маленький размер файла и плохое качество) и Lagarith для финального рендеринга (большой размер, без потери качества). Также пишется лог, в котором фиксируется время работы каждого этапа и размер свободного места на диске - это помогает лучше планировать ночной рендеринг (я вызываю этот скрипт для нескольких файлов из батника и ложусь спать).

Для скрипта нужен VirtualDub (у меня 1.10.4), Deshaker plugin (3.1), ffdshow plugin, Lagarith loseless codec plugin. Также отдельно нужен AviSynth (2.58) c запущенным frameserver.

Всего скрипт состоит из 1 батника и 5 скриптов для vdub’а. Главный HorizonHD.deshake.cmd, его и надо запускать с 4-мя параметрами:
1 - исходный MOV-файл;
2 - путь без \ на конце для сохранения результатов и логов;
3 - номер начального кадра (используйте VirtualDub чтобы выбрать его);
4 - номер завершающего кадра;

Пример:

call HorizonHD.deshake.cmd C:\Capture\file0002.mov H:\temp 1300 9177

Скрипты:

HorizonHD.deshake.cmd

@echo off

if "%4" == "" goto help
goto work

:help
echo Parameters:
echo 1 - source MOV filename;
echo 2 - folder path without last \ to save resulted AVI files (and temporary output);
echo 3 - starting frame (Use VirtualDub to determine it);
echo 4 - end frame (Use VirtualDub to determine it);
goto exit

:work
set source_MOV=%1
set temp_direct_avi=%2\%~n1.temp.direct.AVI
set temp_AVS=%2\%~n1.temp.direct.AVS
set temp_cut_avi=%2\%~n1.temp.cut.lagarith.AVI
set dest_lagarith_avi=%2\%~n1.lagarith.AVI
set dest_ffd_avi=%2\%~n1.ffd.AVI
set start_frame=%3
set end_frame=%4
set log_txt=%2\%~n1.log
set Deshaker_log=%2\%~n1.Deshaker.log

echo .
echo *********************************
echo Source MOV file: %source_MOV%
echo Folder for results and temporary files: %2
echo Starting frame: %start_frame%
echo Ending frame: %end_frame%
echo ********************************
echo Temporary converted MOV to AVI file: %temp_direct_avi%
echo Temporary AviSynth script file: %temp_AVS%
echo Temporary cut AVI file: %temp_cut_avi%
echo Destination Lagarith compressed deshaked file: %dest_lagarith_avi%
echo Destination ffdshow compressed deshaked file: %dest_ffd_avi%
echo Log file: %log_txt%
echo Deshaker log: %Deshaker_log%
echo ---------------------------------------------

echo Source MOV file: %source_MOV% >%log_txt%
echo Folder for results and temporary files: %2 >>%log_txt%
echo Starting frame: %start_frame% >>%log_txt%
echo Ending frame: %end_frame% >>%log_txt%
echo Temporary converted MOV to AVI file: %temp_direct_avi% >>%log_txt%
echo Temporary AviSynth script file: %temp_AVS% >>%log_txt%
echo Temporary cut AVI file: %temp_cut_avi% >>%log_txt%
echo Destination Lagarith compressed deshaked file: %dest_lagarith_avi% >>%log_txt%
echo Destination ffdshow compressed deshaked file: %dest_ffd_avi% >>%log_txt%
echo Deshaker log: %Deshaker_log% >>%log_txt%

set /A frames_length=end_frame-start_frame+1
echo Source frames length: %frames_length%

echo Source frames length: %frames_length% >>%log_txt%

rem Because of each 4th frame deletion, we need to decrease start_frame and frames_length to factor of 3/4;
rem UPD. Actually, just frame_length, not start_frame;

rem UPD. The conversion below is not needed;
rem set /A start_frame=start_frame*3/4
set /A frames_length=frames_length*3/4

rem UPD. Do not output what was not changed;
rem echo Decimated starting frame: %start_frame%
echo Decimated frames length: %frames_length%

echo Decimated frames length: %frames_length% >>%log_txt%

rem Duplicating slashes in Deshaker.log file path;
set Deshaker_log=%Deshaker_log:\=\\%
echo Corrected Deshaker.log path: %Deshaker_log%

echo Corrected Deshaker.log path: %Deshaker_log% >>%log_txt%

echo Generating AVS script: %temp_AVS%
echo Generating AVS script: %temp_AVS% >>%log_txt%

echo DirectShowSource("%temp_direct_avi%") > %temp_AVS%
echo KillAudio() >> %temp_AVS%
rem echo Showframenumber() >> %temp_AVS%
rem UPD. The command below is not needed, because AVSynth somehow decimates proper frames, just need to give a length of 3/4 instead of original;
rem echo SelectEvery(4,0,1,2) >> %temp_AVS%

@echo on
@echo --- Step 1 ----------------------------------------------------------------
@echo --------------------------------------------------------------------------- >>%log_txt%
@dir %2\ /A:D | findstr /C:"bytes free" >>%log_txt%
@time /T >>%log_txt%
@echo vdub /x /i HorizonHD.deshake.1.prep.vdscript "%source_MOV%" "%temp_direct_avi%" >>%log_txt%
vdub /x /i HorizonHD.deshake.1.prep.vdscript "%source_MOV%" "%temp_direct_avi%"

@echo --- Step 2 ------------
@echo -------------------------- >>%log_txt%
@dir %2\ /A:D | findstr /C:"bytes free" >>%log_txt%
@time /T >>%log_txt%
@echo vdub /x /i HorizonHD.deshake.2.cut.vdscript "%temp_AVS%" %start_frame% %frames_length% "%temp_cut_avi%" >>%log_txt%
vdub /x /i HorizonHD.deshake.2.cut.vdscript "%temp_AVS%" %start_frame% %frames_length% "%temp_cut_avi%"

@echo --- Step 3 -------------------
@echo -------------------------------- >>%log_txt%
@dir %2\ /A:D | findstr /C:"bytes free" >>%log_txt%
@time /T >>%log_txt%
@echo vdub /x /i HorizonHD.deshake.3.analyze.vdscript "%temp_cut_avi%" %Deshaker_log% >>%log_txt%
vdub /x /i HorizonHD.deshake.3.analyze.vdscript "%temp_cut_avi%" %Deshaker_log%

@echo --- Step 4 ----------------------------------------------------------------
@echo --------------------------------------------------------------------------- >>%log_txt%
@dir %2\ /A:D | findstr /C:"bytes free" >>%log_txt%
@time /T >>%log_txt%
@echo vdub /x /i HorizonHD.deshake.4.lagarith.vdscript "%temp_cut_avi%" "%dest_lagarith_avi%" %Deshaker_log% >>%log_txt%
vdub /x /i HorizonHD.deshake.4.lagarith.vdscript "%temp_cut_avi%" "%dest_lagarith_avi%" %Deshaker_log%

@echo --- Step 5 ----------------------------------------------------------------
@echo --------------------------------------------------------------------------- >>%log_txt%
@dir %2\ /A:D | findstr /C:"bytes free" >>%log_txt%
@time /T >>%log_txt%
@echo vdub /x /i HorizonHD.deshake.5.ffd.vdscript "%temp_cut_avi%" "%dest_ffd_avi%" %Deshaker_log% >>%log_txt%
vdub /x /i HorizonHD.deshake.5.ffd.vdscript "%temp_cut_avi%" "%dest_ffd_avi%" %Deshaker_log%
@echo off

@echo --------------------------------------------------------------------------- >>%log_txt%
@dir %2\ /A:D | findstr /C:"bytes free" >>%log_txt%
@time /T >>%log_txt%

echo --- Cleanup ----------------------------------------------------------------

rem goto Ex

echo Deleting AVS script: %temp_AVS%
del %temp_AVS%

echo Deleting temporary AVI file: %temp_direct_avi%
del %temp_direct_avi%

echo Deleting temporary cut AVI file: %temp_cut_avi%
del %temp_cut_avi%

@echo Temp. Files removed >>%log_txt%

:Ex
@dir %2\ /A:D | findstr /C:"bytes free" >>%log_txt%

echo --- Done ----------------------------------------------------------------

:exit

HorizonHD.deshake.1.prep.vdscript

// Parameters:
//
// 1 - Source MOV filename;
// 2 - Filename for temporary converted source AVI file;

declare    source_mov;
source_mov = VirtualDub.params[0];

declare    temp_direct_AVI;
temp_direct_AVI = VirtualDub.params[1];

declare msg;

// Converting video to AVI with direct copy;
msg = ">>> Converting source MOV file to AVI: "+source_mov+" to "+temp_direct_AVI;
VirtualDub.Log(msg); VirtualDub.SetStatus(msg);

VirtualDub.Open(source_mov,"",0);
VirtualDub.audio.SetSource(0);
VirtualDub.audio.SetMode(0);
VirtualDub.audio.SetInterleave(1,500,1,0,0);
VirtualDub.audio.SetClipMode(1,1);
VirtualDub.audio.SetEditMode(1);
VirtualDub.audio.SetConversion(0,0,0,0,0);
VirtualDub.audio.SetVolume();
VirtualDub.audio.SetCompression();
VirtualDub.audio.EnableFilterGraph(0);
VirtualDub.video.SetInputFormat(0);
VirtualDub.video.SetOutputFormat(7);
VirtualDub.video.SetMode(0);
VirtualDub.video.SetSmartRendering(0);
VirtualDub.video.SetPreserveEmptyFrames(0);
VirtualDub.video.SetFrameRate2(0,0,1);
VirtualDub.video.SetIVTC(0, 0, 0, 0);
VirtualDub.video.SetCompression();
VirtualDub.video.filters.Clear();
VirtualDub.audio.filters.Clear();
VirtualDub.subset.Delete();
VirtualDub.video.SetRange();
VirtualDub.project.ClearTextInfo();
VirtualDub.SaveAVI(temp_direct_AVI);
VirtualDub.audio.SetSource(1);
VirtualDub.Close();

VirtualDub.Log(">>> Done.");

HorizonHD.deshake.2.cut.vdscript

// Parameters:
//
// 1 - Filename for temporary AVS script filename;
// 2 - Starting frame;
// 3 - Number of frames;
// 4 - Temporary output cut AVI file (Huffman);

declare    temp_AVS;
temp_AVS = VirtualDub.params[0];

declare    start_frame;
start_frame = Sylia.Atoi(VirtualDub.params[1]);

declare    frames_length;
frames_length = Sylia.Atoi(VirtualDub.params[2]);

declare    dest_AVI;
dest_AVI = VirtualDub.params[3];

declare msg;

//--------------------------------------------------
// Cutting video from AVS and converting it into AVI with Huffman compression;
//--------------------------------------------------

msg = ">>> Cut video (start: "+start_frame+", length: "+frames_length+") from AVS script "+temp_AVS+" to AVI file (Huffman): "+dest_AVI;
VirtualDub.Log(msg); VirtualDub.SetStatus(msg);

VirtualDub.Open(temp_AVS,"",0);
VirtualDub.audio.SetSource(1);
VirtualDub.audio.SetMode(0);
VirtualDub.audio.SetInterleave(1,500,1,0,0);
VirtualDub.audio.SetClipMode(1,1);
VirtualDub.audio.SetEditMode(1);
VirtualDub.audio.SetConversion(0,0,0,0,0);
VirtualDub.audio.SetVolume();
VirtualDub.audio.SetCompression();
VirtualDub.audio.EnableFilterGraph(0);
VirtualDub.video.SetInputFormat(0);
VirtualDub.video.SetOutputFormat(7);
VirtualDub.video.SetMode(3);
VirtualDub.video.SetSmartRendering(0);
VirtualDub.video.SetPreserveEmptyFrames(0);
VirtualDub.video.SetFrameRate2(0,0,1);
VirtualDub.video.SetIVTC(0, 0, 0, 0);
VirtualDub.video.SetCompression(0x746d7968,0,10000,0);
VirtualDub.video.filters.Clear();
VirtualDub.audio.filters.Clear();
VirtualDub.subset.Clear();
VirtualDub.subset.AddRange(start_frame,frames_length);
VirtualDub.video.SetRange();
VirtualDub.project.ClearTextInfo();

VirtualDub.SaveAVI(dest_AVI);
VirtualDub.audio.SetSource(1);
VirtualDub.Close();

VirtualDub.Log(">>> Done.");

HorizonHD.deshake.3.analyze.vdscript

// Parameters:
//
// 1 - Input filename;
// 2 - Deshaker log file name with \\ instead of \;

declare    inputFile;
inputFile = VirtualDub.params[0];

declare    log_path;
log_path = VirtualDub.params[1];

declare msg;
declare par;

//--------------------------------------------------
// Deshaker's 1st pass;
//--------------------------------------------------

msg = ">>> Deshaker's 1st pass for AVS stream: "+inputFile;
VirtualDub.Log(msg); VirtualDub.SetStatus(msg);

par = "19|1|30|4|1|0|1|0|640|480|1|1|400|400|1000|0|4|1|0|2|8|30|300|4|"+log_path+"|0|0|0|0|0|0|0|0|0|0|0|0|0|1|5|5|30|1|1|1|50|30|0|0|1|0|1|1|1|30|1000|1|88|1|0|20|5000|100|20|0|0|ff00ff";

VirtualDub.Open(inputFile,"",0);

VirtualDub.audio.SetSource(1);
VirtualDub.audio.SetMode(0);
VirtualDub.audio.SetInterleave(1,500,1,0,0);
VirtualDub.audio.SetClipMode(1,1);
VirtualDub.audio.SetEditMode(1);
VirtualDub.audio.SetConversion(0,0,0,0,0);
VirtualDub.audio.SetVolume();
VirtualDub.audio.SetCompression();
VirtualDub.audio.EnableFilterGraph(0);
VirtualDub.video.SetInputFormat(0);
VirtualDub.video.SetOutputFormat(7);
VirtualDub.video.SetMode(3);
VirtualDub.video.SetSmartRendering(0);
VirtualDub.video.SetPreserveEmptyFrames(0);
VirtualDub.video.SetFrameRate2(0,0,1);
VirtualDub.video.SetIVTC(0, 0, 0, 0);
VirtualDub.video.SetCompression(0x7367616c,0,10000,0);
VirtualDub.video.SetCompData(1,"AA==");
VirtualDub.video.filters.Clear();
VirtualDub.video.filters.Add("Deshaker v3.1");
VirtualDub.video.filters.instance[0].Config(par);
VirtualDub.audio.filters.Clear();

VirtualDub.subset.Delete();
VirtualDub.video.SetRange();
VirtualDub.project.ClearTextInfo();

VirtualDub.RunNullVideoPass();
VirtualDub.audio.SetSource(1);
VirtualDub.Close();

VirtualDub.Log(">>> Done.");

HorizonHD.deshake.4.lagarith.vdscript

// Parameters:
//
// 1 - Input filename;
// 2 - FileName for Lagarith compressed deshaked AVI file;
// 3 - Deshaker log file name with \\ instead of \;

declare    inputFile;
inputFile = VirtualDub.params[0];

declare    dest_lagarith_avi;
dest_lagarith_avi = VirtualDub.params[1];

declare    log_path;
log_path = VirtualDub.params[2];

declare msg;
declare par;

//--------------------------------------------------
// Save ffdshow encoded deshaked video;
//--------------------------------------------------

msg = ">>> Deshaker's 2nd pass. Saving AVI (Lagarith): "+dest_lagarith_avi;
VirtualDub.Log(msg); VirtualDub.SetStatus(msg);

par = "19|2|30|4|1|0|1|0|640|480|1|1|1000|1000|1000|0|4|1|0|2|8|30|300|4|"+log_path+"|0|0|0|0|0|0|0|0|0|0|0|0|0|1|15|15|30|1|1|1|50|30|0|0|1|0|1|1|1|30|1000|1|88|1|0|20|5000|100|20|0|0|ff00ff";

VirtualDub.Open(inputFile,"",0);

VirtualDub.audio.SetSource(1);
VirtualDub.audio.SetMode(0);
VirtualDub.audio.SetInterleave(1,500,1,0,0);
VirtualDub.audio.SetClipMode(1,1);
VirtualDub.audio.SetEditMode(1);
VirtualDub.audio.SetConversion(0,0,0,0,0);
VirtualDub.audio.SetVolume();
VirtualDub.audio.SetCompression();
VirtualDub.audio.EnableFilterGraph(0);
VirtualDub.video.SetInputFormat(0);
VirtualDub.video.SetOutputFormat(7);
VirtualDub.video.SetMode(3);
VirtualDub.video.SetSmartRendering(0);
VirtualDub.video.SetPreserveEmptyFrames(0);
VirtualDub.video.SetFrameRate2(0,0,1);
VirtualDub.video.SetIVTC(0, 0, 0, 0);
VirtualDub.video.SetCompression(0x7367616c,0,10000,0);
VirtualDub.video.SetCompData(1,"AA==");
VirtualDub.video.filters.Clear();
VirtualDub.video.filters.Add("Deshaker v3.1");
VirtualDub.video.filters.instance[0].Config(par);
VirtualDub.audio.filters.Clear();

VirtualDub.subset.Delete();
VirtualDub.video.SetRange();
VirtualDub.project.ClearTextInfo();

VirtualDub.SaveAVI(dest_lagarith_avi);
VirtualDub.audio.SetSource(1);
VirtualDub.Close();

VirtualDub.Log(">>> Done.");

HorizonHD.deshake.5.ffd.vdscript

// Parameters:
//
// 1 - Input filename;
// 2 - FileName for ffdshow compressed deshaked AVI file;
// 3 - Deshaker log file name with \\ instead of \;

declare    inputFile;
inputFile = VirtualDub.params[0];

declare    dest_ffd_avi;
dest_ffd_avi = VirtualDub.params[1];

declare    log_path;
log_path = VirtualDub.params[2];

declare msg;
declare par;

//--------------------------------------------------
// Save ffdshow encoded deshaked video;
//--------------------------------------------------

msg = ">>> Deshaker's 2nd pass. Saving AVI (ffdshow): "+dest_ffd_avi;
VirtualDub.Log(msg); VirtualDub.SetStatus(msg);

par = "19|2|30|4|1|0|1|0|640|480|1|1|1000|1000|1000|0|4|1|0|2|8|30|300|4|"+log_path+"|0|0|0|0|0|0|0|0|0|0|0|0|0|1|15|15|30|1|1|1|50|30|0|0|0|0|1|1|1|30|1000|1|88|1|0|20|5000|100|20|0|0|ff00ff";

VirtualDub.Open(inputFile,"",0);
VirtualDub.audio.SetSource(1);
VirtualDub.audio.SetMode(0);
VirtualDub.audio.SetInterleave(1,500,1,0,0);
VirtualDub.audio.SetClipMode(1,1);
VirtualDub.audio.SetEditMode(1);
VirtualDub.audio.SetConversion(0,0,0,0,0);
VirtualDub.audio.SetVolume();
VirtualDub.audio.SetCompression();
VirtualDub.audio.EnableFilterGraph(0);
VirtualDub.video.SetInputFormat(0);
VirtualDub.video.SetOutputFormat(7);
VirtualDub.video.SetMode(3);
VirtualDub.video.SetSmartRendering(0);
VirtualDub.video.SetPreserveEmptyFrames(0);
VirtualDub.video.SetFrameRate2(0,0,1);
VirtualDub.video.SetIVTC(0, 0, 0, 0);
VirtualDub.video.SetCompression(0x73646666,0,10000,0);
VirtualDub.video.SetCompData(2398,"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");
VirtualDub.video.filters.Clear();
VirtualDub.video.filters.Add("Deshaker v3.1");
VirtualDub.video.filters.instance[0].Config(par);
VirtualDub.audio.filters.Clear();
VirtualDub.subset.Delete();
VirtualDub.video.SetRange();
VirtualDub.project.ClearTextInfo();
VirtualDub.SaveAVI(dest_ffd_avi);
VirtualDub.audio.SetSource(1);
VirtualDub.Close();

VirtualDub.Log(">>> Done.");
  • 1101
Comments
zavtrak

так работает эмпег сжатие, 3й кадр - ключевой, а на формирование следующего кадра мозгов не хватает и для отсутствия разрывов делается такая штука я полагаю.
повторяется ли такое при съёмке с другими разрешениями и fps?

Prikupets

Не знаю, на FullHD-30 желе, так что я пользуюсь только 720p-60.

Забыл, кстати, написать, что побочном эффектом работы моего скрипта является ускорение видео на 25%, что, на мой взгляд, прибавляет ему толику бодрости 😉