Фактическая продолжительность видео и файлов aufio

#c# #audio #video #ffmpeg #ffprobe

#c# #Аудио #Видео #ffmpeg #ffprobe

Вопрос:

На данный момент я работаю над приложением, которое позволяет записывать видеофайлы. Параллельно с видеофайлом записывается аудиофайл. В конце концов, есть два файла: .mp4 и .wav .

Моя цель — объединить эти два файла. Для этого файлы должны быть примерно одинаковой продолжительности. Чтобы определить, имеют ли видео и аудиофайлы одинаковую продолжительность, я провел серию экспериментов. Я записал видео: 5 раз по 15 минут, 5 раз по 30 минут, 5 раз по 45 минут и 5 раз по 60 минут.

Во время экспериментов я записал следующие значения:

  1. Время создания файла (с точностью до мс).
     IDateTime videoCreated = _fileWrapper.GetCreationTime(videoPath);
    
    IDateTime audioCreated = _fileWrapper.GetCreationTime(audioPath);
     
  2. Время последнего изменения файла (с точностью до мс).
     IDateTime videoModified = _fileWrapper.GetLastWriteTime(videoPath);
    
    IDateTime audioModified = _fileWrapper.GetLastWriteTime(audioPath);
     
  3. Я измерил продолжительность файлов с помощью ffprobe.
  4. Я также вычислил длину файлов, вычтя время создания файла из времени последнего изменения. Назовем это значение вычисленной продолжительностью.

Далее я опишу полученные результаты.

Если принять во внимание рассчитанную продолжительность, то видео- и аудиофайлы будут примерно одинаковыми. Аудиофайлы немного короче видеофайлов (в среднем 0,415 с, что незначительно).

Давайте перейдем к длительности с помощью ffprobe. Аудиофайлы значительно длиннее видеофайлов. Ниже приведена средняя разница между аудио- и видеофайлами по группам:

 15 min -12,426 s;
30 min -16,942 s;
45 min -31,403 s;
60 min -34,702 s.
 

Результаты только для аудиофайлов:

Длительность ffprobe немного меньше расчетной продолжительности. Ниже приведена средняя разница в разных группах:

 15 min - 0,424 s;
30 min - 1,129 s;
45 min - 1,816 s;
60 min - 2,292 s.
 

Результаты только для видеофайлов:

Длительность по ffprobe значительно меньше расчетной продолжительности. Групповые результаты:

 15 min -13,171 s;
30 min -18,630 s;
45 min -33,666 s;
15 min -37,326 s.
 

Почему длительность по ffprobe меньше вычисленной длительности? Как объяснить все эти наблюдения? Какова фактическая продолжительность файлов?

Обновлено. форматы: видео — .mp4, аудио — .пример команды wav ffprobe: ffprove exampleFileName -v info -hide_banner -show_entries поток =длительность xml

Запись видео. Vlc.DotNet.Используется базовая библиотека.

 public void Execute(object parameter)
        {        
            if (_videoRecorder != null amp;amp; _videoRecorder.IsPlaying())
            {
                _videoRecorder.Stop(); //!!!
                _videoRecorder = null;

                TimeSpan videoRecordingTime = TimeSpan.Zero; OnRecordingStopped?.Invoke(sessionService.CurrentDevice.Device.Id, videoRecordingTime);
                return;
            }
            _videoRecorder = new VlcMediaPlayer(_vlcLibDirectory.DirectoryInfo);

            _filenameGenerator.Folder = sessionService.PatientVideoDirectory;
            _filenameGenerator.GenerateNextFileName();
            string fileName = _filenameGenerator.GetName();

            string fileDestination = Path.Combine(_filenameGenerator.FolderPath, fileName);

            string[] mediaOptions =
            {
                ":sout=#file{dst='"   fileDestination   "'}",
//                ":live-caching=0",// TODO: check what that parameter does!
                ":sout-keep" /*Keep sout open (default disabled) : use the same sout instance across the various playlist items, if possible.*/
//                ":file-logging", ":vvv", ":extraintf=logger", ":logfile=VlcLogs.log"
            };

            _videoRecorder.SetMedia(sessionService.CurrentDevice.MediaStreamUri, mediaOptions); _videoRecorder.Play();

            OnRecordingStarted?.Invoke(fileName);
        }
 

Запись звука. Используется фреймворк NAudio.

 private void StartRecording()
        {
            try
            {
                string patientFolder = Patient.GetString();
                _waveFileDestination = string.Empty;

                if (IsForVideo)
                {
                    _waveFileDestination = Path.Combine(_systemSetting.VideoServerPath, patientFolder,
                        _videoFileNameGenerator.GetCurrentNameWithExtension("wav"));
                }
                else
                {
                    _audioFileNameGenerator.Folder = Path.Combine(_systemSetting.AudioPath, patientFolder);
                    _audioFileNameGenerator.GenerateNextFileName();
                    _waveFileDestination = Path.Combine(_audioFileNameGenerator.FolderPath,
                        _audioFileNameGenerator.GetName());
                }

                _waveSource = new WaveInEvent
                {
                    DeviceNumber = CapturingDevice.Number,
                    WaveFormat = new WaveFormat(44100, 1)
                };

                _waveSource.DataAvailable  = WaveSourceOnDataAvailable;
                _waveSource.RecordingStopped  = WaveSourceOnRecordingStopped;

                _waveFile = new WaveFileWriter(_waveFileDestination, _waveSource.WaveFormat);

                _waveSource.StartRecording();

                if (!IsForVideo)
                {
                    // Save audio media entity
                    _recordingMediaId = Media.AddToLocation(Patient.Id,
                        ExaminationId, _audioFileNameGenerator.GetName(),
                        MediaType.Audio, 0, _workstation.LocationId, DateTime.Now);
                    Media newMedia = Media.Get(_recordingMediaId);

                    MediaItem mediaItem = new MediaItem(newMedia, _systemSetting, _mediaManager)
                    {
                        PatientSsn = newMedia.AccessionNumber
                    };

                    OnAudioAdded(mediaItem);
                }

            }
            catch (Exception exception)
            {

            }
            finally
            {

            }
        }

private void StopRecording()
        {

            try
            {

                _waveSource.StopRecording();

                if (!IsForVideo)
                {
                    Media media = Media.Get(_recordingMediaId);    
                    media.Duration = Duration.Seconds;
                    Media.Update(media);
                    _recordingMediaId = 0;
                }
                else
                {
                    IsForVideo = false;
                }
            }
            catch (Exception exception)
            {
            }

            OnStateChanged();
        }
 

Комментарии:

1. Было бы лучше записывать как видео, так и аудио в один и тот же файл, чтобы легко сохранять изохронность между видео и аудио «кадрами».

2. К сожалению, это невозможно.

3. Какие форматы? Какова ваша команда ffprobe? Как вы записываете файлы?

4. Обновил мой пост.

5. Вы используете VLC для создания видеофайла… Я почти уверен, что вы также можете микшировать аудио из другого источника, если только я все еще чего-то не упускаю.