Разделите файл .wav в соответствии с частотой кадров видео в Matlab.

У меня есть видео yuv (скажем, stream.yuv) и соответствующий аудиофайл (stream.wav). Теперь у меня есть графический интерфейс, который отображает необработанное видео кадр за кадром. Проблема, с которой я сейчас сталкиваюсь, заключается в том, что мне нужно воспроизводить звук, связанный с каждым видеокадром.

Я пробовал следующее для начала, но когда я выполняю это, звук прерывается

%% Dividing the audio into per-second samples
nframes = 720;
[audioFile, audioSampleFreq] = audioread('stream.wav');
numSamples = length(audioFile); 
audioLength = round(numSamples / audioSampleFreq);

for frame = 1:audioLength
    start = (frame-1)*audioSampleFreq+1;
    stop = frame*audioSampleFreq; 
    [start stop]
    audioFrame1 = audioFile(start:stop,:);
    sound(audioFrame1,audioSampleFreq);
end

Чтобы разделить звук на сэмплы на видеокадр,

    audioFileName = 'stream.wav';
    nframes = 720;
    framerate = 25;
    [audioFile, audioSampleFreq] = audioread(audioFileName);

    audioFRate = round(audioSampleFreq/framerate);

    %% Total number of audio samples
    numSamples = length(audioFile); 

    %% number of audio frames
    numFrames = floor(numSamples/audioFRate);  

    for frame = 1:numFrames
        start = (frame-1)*audioFRate+1;
        stop = frame*audioFRate; 
        [start stop]
        audioFrame1 = audioFile(start:stop,:);
        sound(audioFrame1,audioSampleFreq);   
    end

Любые мысли о том, как синхронизировать покадровый рендеринг кадров YUV и посекундных аудиосэмплов? Спасибо!


person deeptigp    schedule 28.11.2015    source источник


Ответы (1)


Мне кажется, вы неправильно подошли к проблеме. Адаптация вашего аудиосигнала к видеосигналу, как правило, происходит неправильно, потому что небольшие сбои в аудиопотоке очень заметны, а средний зритель не замечает пропущенных кадров. Вместо этого синхронизируйте видеосигнал с аудиосигналом. Чтобы быстро начать, настройте аудиоплеер и начните с такого кода:

videorate=25 %fps
audiorate=audio.SampleRate %sample rate
while audio.isplaying()
   displayFrame(ceil(audio.CurrentSample/audiorate*videorate))
end

Многое можно улучшить, но я предполагаю, что эта простая реализация уже покажет лучшие результаты, чем ваша текущая попытка.

Что улучшить

  • Не визуализируйте один и тот же кадр дважды.
  • ceil - это просто быстрое и грязное приближение. Вместо этого вам нужно вызвать displayFrame для кадра f в момент времени f/fps-processing_delay, где processing_delay — это время между вызовом displayFrame и фактическим появлением изображения на экране. Сначала установите его на 1/25 и настройте вручную, если звук и видео не синхронизированы.
  • Если вы пропустили время, когда вы должны позвонить displayFrame, примите решение. Для небольших промежутков по-прежнему отображайте рамку, для больших промежутков отбрасывайте рамку и переходите к следующей. Может быть, пауза для отображения не рано.
  • Когда ваш видеосигнал действительно испортился, например. выпадение 15 из последних 25 кадров, проверьте возможные причины. При обработке необработанного видео высокого разрешения это обычно происходит из-за того, что ваш жесткий диск работает медленно, поэтому кратковременная приостановка видео и звука должна позволить буферам снова заполниться.

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

person Daniel    schedule 28.11.2015
comment
Спасибо за ответ. Вы сказали, что один и тот же кадр не должен рендериться дважды. Я думаю, что это конфликтует с параметром, который вы передаете функции displayFrame. Например, тестовый файл .wav имеет частоту дискретизации 44100 и всего 1323000 выборок. Теперь для этого видео, если я буду следовать циклу while, который вы упомянули выше, это будет эквивалентно for i = 1: numSamples displayFrame(ceil((i/sampleRate)*fps)) end Это будет рендерить один и тот же кадр несколько раз. Я что-то упускаю? - person deeptigp; 01.12.2015