c# - 视频和aufio文件的实际时长
问题描述
目前我正在开发一个可以录制视频文件的应用程序。与视频文件并行记录音频文件。最终,有两个文件:.mp4
和.wav
.
我的目的是合并这两个文件。为此,文件的持续时间应大致相同。为了确定视频和音频文件的持续时间是否相等,我进行了一批实验。我录制的视频:5 次 15 分钟,5 次 30 分钟,5 次 45 分钟,5 次 60 分钟。
在实验期间,我捕获了下一个值:
文件创建时间(精确到毫秒)。
IDateTime videoCreated = _fileWrapper.GetCreationTime(videoPath); IDateTime audioCreated = _fileWrapper.GetCreationTime(audioPath);
文件最后修改时间(精确到毫秒)。
IDateTime videoModified = _fileWrapper.GetLastWriteTime(videoPath); IDateTime audioModified = _fileWrapper.GetLastWriteTime(audioPath);
我在 ffprobe 的帮助下测量了文件的持续时间。
我还计算了文件的长度,从上次更改的时间中减去文件的创建时间。让我们将此值称为计算的持续时间。
接下来,我将描述我得到的结果。
如果我们考虑计算的持续时间,则视频和音频文件大致相同。音频文件比视频文件略短(平均 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();
}
解决方案
推荐阅读
- haxeflixel - HaxeFlixel 无法编译为 HTML5
- javascript - 在数组javascript中获取对象
- sql - 对两个不同列中的不同项目求和
- javascript - ''检测'' 如果用户使用 javascript 输入了一个单词序列
- android - 从片段访问活动菜单项并隐藏onButton单击android
- typescript - 在 TS 文件中导入时找不到节点本机模块
- python - 同时运行 jupyter notebook 单元?
- php - PHP 代码 INCLUDE 在通过 $Value 回显时留下一个数字
- reactjs - Redux + React如何仅更改充满对象的数组中的一个元素值?我有工作应用程序,只是想确保我做对了
- java - 如何为具有相同内容的多个片段创建片段模板(具有变量和方法的类、布局)?