0

At the moment I am working on an application that enables to record video files. In parallel with a video file, an audio file is recorded. Eventually, there are two files: .mp4 and .wav.

My purpose is to merge those two files. To do so the files should be of approximately the same duration. In order to determine if video and audio files are of equal duration, I have conducted a batch of experiments. I have recorded videos: 5 times for 15 minutes, 5 times for 30 minutes, 5 times for 45 minutes and 5 times for 60 minutes.

During the experiments I captured the next values:

  1. File creation time (accurate to ms).

    IDateTime videoCreated = _fileWrapper.GetCreationTime(videoPath);
    
    IDateTime audioCreated = _fileWrapper.GetCreationTime(audioPath);
    
  2. File last modification time (accurate to ms).

    IDateTime videoModified = _fileWrapper.GetLastWriteTime(videoPath);
    
    IDateTime audioModified = _fileWrapper.GetLastWriteTime(audioPath);
    
  3. I measured the duration of files with the help of ffprobe.

  4. I also calculated the length of the files, subtracting the time the file was created from the time of the last change. Let's call this value the calculated duration.

Next, I'll describe the results I got.

If we take into account the calculated duration, the video and audio files are approximately the same. Audio files are slightly shorter than video files (on average 0,415 s, which is insignificant).

Let's move on to the duration by ffprobe. Audio files are significantly longer than video files. The following is the average difference between audio and video files by group:

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

Results for audio files only:

The duration of ffprobe is slightly smaller than the calculated duration. Below is the average difference in different groups:

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

Results for video files only:

The duration by ffprobe is significantly smaller than the calculated duration. Group results:

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

Why the duration by ffprobe is less than computed duration? How to explain all these observations? What is the actual duration of the files?

Updated. formats: video - .mp4, audio - .wav ffprobe command example: ffprove exampleFileName -v info -hide_banner -show_entries stream=duration -of xml

Video recording. Vlc.DotNet.Core library is used.

public void Execute(object parameter)
        {        
            if (_videoRecorder != null && _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);
        }

Audio recording. NAudio framework is used.

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();
        }
Liidia
  • 55
  • 8

0 Answers0