#c# #audio #video #ffmpeg #ffprobe
#c# #Аудио #Видео #ffmpeg #ffprobe
Вопрос:
На данный момент я работаю над приложением, которое позволяет записывать видеофайлы. Параллельно с видеофайлом записывается аудиофайл. В конце концов, есть два файла: .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 поток =длительность 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 для создания видеофайла… Я почти уверен, что вы также можете микшировать аудио из другого источника, если только я все еще чего-то не упускаю.