首页 > 解决方案 > 视频和aufio文件的实际时长

问题描述

目前我正在开发一个可以录制视频文件的应用程序。与视频文件并行记录音频文件。最终,有两个文件:.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 stream=duration -of xml

视频录制。使用 Vlc.DotNet.Core 库。

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);
        }

声音录制。使用 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();
        }

标签: c#audiovideoffmpegffprobe

解决方案


推荐阅读