Продолжение прерванной сборки потоком — с недописанного файла
Потоком кэша кусков нет, и продолжать было не с чего. Но недописанный файл сам по себе — уже собранная часть фильма: в нём видно, сколько целых кадров успело записаться. Программа отступает до границы последнего целого куска, переносит эту часть и досылает остаток. Дописать в конец существующего MKV нельзя, поэтому продолжение пишется в новый файл. MP4 продолжать нельзя вовсе: оглавление в конце, и оборванный файл не открывается — об этом говорится прямо. Готовый файл теперь цел до последнего: сборка идёт в файл рядом и занимает место готового, только когда дописана. Сорвавшаяся попытка не отбирает уже собранное — из двух недописанных остаётся тот, где кадров больше, и считаются они даже после запроса остановки. Отдельно пришлось снять сдвиг, который приёмник накладывает на весь ролик: перенесённая часть несла его в себе, и куски за ней задваивали кадр. Замерено: обрыв в четырёх разных местах, продолженная сборка каждый раз совпала с собранной за один раз попиксельно. В nlvetool у render появились --cancel-after=<сек> и сочетание слов: cache resume проверяет, что старый путь через кэш не сломался.
This commit is contained in:
parent
38f4b295b9
commit
4522f0000a
4 changed files with 346 additions and 35 deletions
|
|
@ -21,9 +21,12 @@
|
|||
собрать проект-образец: видео внизу, картинка
|
||||
сверху посередине, дыра в начале
|
||||
render <проект.nlve> <выход> [burn|keep|resume|cache]
|
||||
[--cancel-after=<сек>]
|
||||
уплотить проект, создать вставки, собрать ролик
|
||||
и сверить число кадров; cache — собрать
|
||||
по-старому, через кэш кусков
|
||||
по-старому, через кэш кусков; --cancel-after
|
||||
оборвёт сборку на полпути, а resume продолжит
|
||||
её с недописанного файла
|
||||
subs <проект.nlve>
|
||||
собрать разметку субтитров из текстовых клипов
|
||||
и напечатать её
|
||||
|
|
@ -1525,8 +1528,34 @@ var
|
|||
Rep: TExportReport;
|
||||
I: Integer;
|
||||
WantSum: Int64;
|
||||
Ok: Boolean;
|
||||
Ok, Stopped: Boolean;
|
||||
CancelAfter, Waited: Double;
|
||||
|
||||
{ Слова после выхода идут в любом порядке и сочетаются: cache resume —
|
||||
это «по-старому и продолжая». }
|
||||
function HasWord(const AWord: string): Boolean;
|
||||
var
|
||||
J: Integer;
|
||||
begin
|
||||
Result := False;
|
||||
for J := 4 to ParamCount do
|
||||
if LowerCase(ParamStr(J)) = AWord then
|
||||
Exit(True);
|
||||
end;
|
||||
|
||||
begin
|
||||
{ Отдельно от слов может стоять --cancel-after=<сек>: оборвать сборку
|
||||
на полпути, чтобы было что продолжать. }
|
||||
CancelAfter := 0;
|
||||
for I := 4 to ParamCount do
|
||||
if Copy(ParamStr(I), 1, 15) = '--cancel-after=' then
|
||||
if not TryStrToFloat(Copy(ParamStr(I), 16, MaxInt), CancelAfter,
|
||||
InvariantFormat) then
|
||||
begin
|
||||
WriteLn('Не удалось разобрать значение --cancel-after');
|
||||
Halt(2);
|
||||
end;
|
||||
|
||||
Proj := TProject.Create;
|
||||
try
|
||||
if not Proj.LoadFromFile(ExpandFileName(ParamStr(2)), Err) then
|
||||
|
|
@ -1588,7 +1617,7 @@ begin
|
|||
{ Вжигание текста — последним, уже по окончательному списку кусков:
|
||||
повторное уплощение стёрло бы отметки о разметке. Так же устроено и
|
||||
окно сборки. }
|
||||
if (ParamCount >= 4) and (LowerCase(ParamStr(4)) = 'burn') then
|
||||
if HasWord('burn') then
|
||||
WriteLn('вжигаю текст, пересобрать придётся ',
|
||||
SecondsToStr(BurnTextIntoSegments(Proj, Segs, Proj.CacheDir)), ' с');
|
||||
|
||||
|
|
@ -1597,22 +1626,34 @@ begin
|
|||
чего собрался ролик. }
|
||||
Thread := TExportThread.Create(Segs, AudioSegs,
|
||||
ExpandFileName(ParamStr(3)),
|
||||
(ParamCount >= 4) and (LowerCase(ParamStr(4)) = 'keep'),
|
||||
HasWord('keep'),
|
||||
Proj.Master, Default(TEncodeProfile));
|
||||
{ Словом resume просят продолжить прерванную сборку: готовые куски
|
||||
берутся с диска, а не считаются заново. }
|
||||
Thread.Resume := (ParamCount >= 4) and (LowerCase(ParamStr(4)) = 'resume');
|
||||
Thread.Resume := HasWord('resume');
|
||||
{ Словом cache просят собрать по-старому, через кэш кусков: так два
|
||||
способа сверяются между собой на одном и том же монтаже. }
|
||||
Thread.AllowStream := not ((ParamCount >= 4) and
|
||||
(LowerCase(ParamStr(4)) = 'cache'));
|
||||
Thread.AllowStream := not HasWord('cache');
|
||||
Watcher := TExportWatcher.Create(Thread);
|
||||
try
|
||||
Thread.OnProgress := @Watcher.Progress;
|
||||
Thread.OnLog := @Watcher.LogLine;
|
||||
Thread.Start;
|
||||
{ Остановка на полпути: так получается недописанный файл, с
|
||||
которого потом просят продолжить. }
|
||||
Waited := 0;
|
||||
Stopped := False;
|
||||
while not Thread.Finished do
|
||||
begin
|
||||
CheckSynchronize(100);
|
||||
Waited := Waited + 0.1;
|
||||
if (CancelAfter > 0) and (not Stopped) and (Waited >= CancelAfter) then
|
||||
begin
|
||||
Stopped := True;
|
||||
WriteLn('[тест] запрашиваю остановку');
|
||||
Thread.RequestCancel;
|
||||
end;
|
||||
end;
|
||||
CheckSynchronize(0);
|
||||
Rep := Thread.Report;
|
||||
finally
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue