Вставки тишины для звука делаются без картинки

Звук пропадал кусками, и причина оказалась не в громкости и не в
раскладке дорожек: обе были верны. Дыры на звуковой дорожке заполнялись
тем же чёрным клипом, что и дыры на видеодорожке, а опорные кадры в нём
стоят через 4.171 с. Перемотка внутри такой вставки откатывается к
ближайшему опорному кадру, дорожка начинает отдавать звук на несколько
секунд раньше соседних, смешивание равняется по ней — и содержимое
соседней дорожки в это окно не попадает.

Замерено на файле, без запуска окна. Смешивание трёх дорожек проекта:

  старт  0 с: -23.3 dB     старт 24 с: -91.0 dB   (полная тишина)
  старт 12 с: -10.1 dB     старт 30 с: -18.0 dB

При этом та же дорожка A2 отдельно на 24-й секунде даёт -11.7 dB, то
есть содержимое на месте. Смешивание A2 с A4 работает, A1 с A2 — нет:
у A1 в этой точке идёт длинная чёрная вставка, и перемотка в ней
откатывается на 3.1 с назад.

Теперь у звуковых дорожек своя вставка — anullsrc в звуковом кодеке
проекта, без видеопотока. В звуке опорным является каждый кадр, и
отката нет. После правки во всех проверенных точках звук есть:

  0 с -24.1   7 с -19.0   12 с -11.9   18 с -17.5   24 с -11.7
  25 с  -9.6  30 с  -9.5  40 с -15.6   60 с -19.5   72 с -15.9

Сборка ролика от этого не страдает: она декодирует куски в отсчёты, и
файл без картинки ей подходит так же.

Заодно в служебную программу добавлена команда audio: раскладка
звуковых дорожек проекта на куски вместе со строками edl://. Ею это и
было найдено.
This commit is contained in:
4aiman 2026-08-21 12:58:13 +03:00
commit ad88683e8b
4 changed files with 141 additions and 2 deletions

View file

@ -23,6 +23,9 @@
render <проект.nlve> <выход>
уплотить проект, создать вставки, собрать ролик
и сверить число кадров
audio <проект.nlve>
разложить звуковые дорожки проекта на куски и
напечатать их вместе со строками edl://
buildcut <проект.nlve> <видео>
проект из одного файла с точным резом в заведомо
неопорной точке
@ -858,6 +861,85 @@ begin
WriteLn(' ', FThread.PendingLog);
end;
{ Раскладка звуковых дорожек.
Нужна потому, что «звука нет вот здесь» глазами не разобрать: громкость
может быть верной, а кусок в этом месте — ссылаться не туда. Здесь
печатается ровно то, что уходит в плеер: место на монтаже, файл, место
в файле, длина. }
procedure CmdAudio;
var
Proj: TProject;
Segs: TFlatSegmentArray;
Missing: TGenRequests;
Err: string;
I, J: Integer;
Total, At: Double;
Kind: string;
begin
Proj := TProject.Create;
try
if not Proj.LoadFromFile(ExpandFileName(ParamStr(2)), Err) then
begin
WriteLn('Не удалось прочитать проект: ', Err);
Halt(1);
end;
Total := Max(AudibleEnd(Proj, tkVideo), AudibleEnd(Proj, tkAudio));
WriteLn('проект: ', Proj.FileName);
WriteLn('длина слышимого: ', SecondsToStr(Total), ' с');
WriteLn;
for I := 0 to Proj.TrackCount - 1 do
begin
if Proj.Tracks[I].Kind <> tkAudio then
Continue;
WriteLn('=== ', Proj.Tracks[I].Name, ' ===');
if not Proj.TrackAudible(Proj.Tracks[I]) then
begin
WriteLn(' не слышна (заглушена или пуста)');
WriteLn;
Continue;
end;
if Proj.Tracks[I].Count = 0 then
begin
WriteLn(' клипов нет');
WriteLn;
Continue;
end;
if not FlattenAudioTrack(Proj, Proj.Tracks[I], Total, Segs, Missing) then
begin
WriteLn(' разложить не удалось');
WriteLn;
Continue;
end;
At := 0;
for J := 0 to High(Segs) do
begin
if Segs[J].Kind = skBlack then
Kind := 'тишина'
else
Kind := 'звук ';
WriteLn(Format(' [%2d] %s монтаж %8s..%8s длина %8s из %8s %s',
[J, Kind, SecondsToStr(At), SecondsToStr(At + Segs[J].Duration),
SecondsToStr(Segs[J].Duration), SecondsToStr(Segs[J].SrcStart),
ExtractFileName(Segs[J].FilePath)]));
if (Segs[J].Kind = skBlack) and (not FileExists(Segs[J].FilePath)) then
WriteLn(' ВНИМАНИЕ: вставки тишины нет на диске');
At := At + Segs[J].Duration;
end;
WriteLn(' всего по дорожке: ', SecondsToStr(At), ' с');
WriteLn;
WriteLn(' ', BuildEdlUri(Segs));
WriteLn;
end;
finally
Proj.Free;
end;
end;
procedure CmdRender;
var
Proj: TProject;
@ -999,6 +1081,8 @@ begin
CmdBuild
else if (Cmd = 'buildcut') and (ParamCount >= 3) then
CmdBuildCut
else if (Cmd = 'audio') and (ParamCount >= 2) then
CmdAudio
else if (Cmd = 'render') and (ParamCount >= 3) then
CmdRender
else