С# Получить продолжительность видеофайла из метаданных
Я пытаюсь читать метаданные из файла. Мне нужно только свойство Video → Length, однако я не могу найти простой способ прочитать эту информацию.
Я понял, что это будет довольно легко, поскольку по умолчанию это видно в Explorer, однако это выглядит намного сложнее, чем я ожидал. Ближе всего я пришел:
Microsoft.DirectX.AudioVideoPlayback.Video video = new Microsoft.DirectX.AudioVideoPlayback.Video(str);
double duration = video.Duration;
Однако это вызывает исключение LoaderLock, и я не знаю, как с этим бороться.
Любые идеи?
Ответы
Ответ 1
Многие из этих сведений предоставлены оболочкой, поэтому вы можете сделать это, добавив ссылку на библиотеку COM "Microsoft Shell Controls and Automation" (Shell32), а затем используя метод Folder.GetDetailsOf для запроса расширенной информации,
Я недавно искал это и наткнулся на на этот вопрос на форумах MSDN С# General. Я закончил писать это как метод расширения в FileInfo:
public static Dictionary<string, string> GetDetails(this FileInfo fi)
{
Dictionary<string, string> ret = new Dictionary<string, string>();
Shell shl = new ShellClass();
Folder folder = shl.NameSpace(fi.DirectoryName);
FolderItem item = folder.ParseName(fi.Name);
for (int i = 0; i < 150; i++)
{
string dtlDesc = folder.GetDetailsOf(null, i);
string dtlVal = folder.GetDetailsOf(item, i);
if (dtlVal == null || dtlVal == "")
continue;
ret.Add(dtlDesc, dtlVal);
}
return ret;
}
Если вы ищете конкретные записи, вы можете сделать что-то подобное, хотя гораздо быстрее узнать, какой индекс эти записи (длина - индекс 27, я считаю), и просто запросить их. Заметьте, я не много разбирался в том, может ли индекс измениться (я сомневаюсь), поэтому я применил словарь.
Ответ 2
Взгляните на этот вопрос SO - Solid FFmpeg wrapper для С#/. NET, который ссылается на несколько реализаций ffmpeg.Net. ffmpeg работает с большинством видеоформатов/кодеков. Таким образом, вам не нужно беспокоиться о том, что кодек установлен на компьютере.
Или посмотрите http://mediainfo.sourceforge.net/en.
Ответ 3
Я бы просто прокомментировал сообщение Микаэля, но у меня пока нет достаточного количества повторений. Я согласен с ним в использовании ffmpeg, чтобы вам не требовалось устанавливать кодеки. Вы можете просто проанализировать вывод "ffmpeg -i your_filename", который просто сбрасывает некоторую информацию о видео, включая продолжительность.
Я не знаю, с какими кодеками вы работаете, но некоторые контейнеры фактически не сохраняют продолжительность в метаданных (это распространено для потоковых контейнеров, поскольку продолжительность неизвестна). Я не знаю, как это работает ffmpeg, но, похоже, это как-то (возможно, путем разбора всего файла для временных кодов).
Ответ 4
Я рекомендую использовать MediaToolkit пакет nuget. Это не требует COM-взаимодействия вашего кода.
using MediaToolkit;
// a method to get Width, Height, and Duration in Ticks for video.
public static Tuple<int, int, long> GetVideoInfo(string fileName)
{
var inputFile = new MediaToolkit.Model.MediaFile { Filename = fileName };
using (var engine = new Engine())
{
engine.GetMetadata(inputFile);
}
// FrameSize is returned as '1280x768' string.
var size = inputFile.Metadata.VideoData.FrameSize.Split(new[] { 'x' }).Select(o => int.Parse(o)).ToArray();
return new Tuple<int, int, long>(size[0], size[1], inputFile.Metadata.Duration.Ticks);
}
Ответ 5
используя DirectShowLib (http://directshownet.sourceforge.net/)
/// <summary>
/// Gets the length of the video.
/// </summary>
/// <param name="fileName">Name of the file.</param>
/// <param name="length">The length.</param>
/// <returns></returns>
static public bool GetVideoLength(string fileName, out double length)
{
DirectShowLib.FilterGraph graphFilter = new DirectShowLib.FilterGraph();
DirectShowLib.IGraphBuilder graphBuilder;
DirectShowLib.IMediaPosition mediaPos;
length = 0.0;
try
{
graphBuilder = (DirectShowLib.IGraphBuilder)graphFilter;
graphBuilder.RenderFile(fileName, null);
mediaPos = (DirectShowLib.IMediaPosition)graphBuilder;
mediaPos.get_Duration(out length);
return true;
}
catch
{
return false;
}
finally
{
mediaPos = null;
graphBuilder = null;
graphFilter = null;
}
}
Ответ 6
Получение продолжительности видео файла в Win Rt App или Metro С#:
StorageFile videoFile;
videoFile = await StorageFile.GetFileFromPathAsync(VIDEO_PATH_HERE);
Windows.Storage.FileProperties.VideoProperties x = await videoFile.Properties.GetVideoPropertiesAsync();
var videoDuration = x.Duration;
Ответ 7
MediaInfo - отличная библиотека с открытым исходным кодом для этой цели (DLL лицензируется LGPL). Пакет загрузки содержит пример приложения в С# (под Developers\Project\MSCS\Example
)
Ответ 8
У меня была такая же проблема с небольшим приложением для предварительного просмотра видео.
Проблема - Assassent Assassent. Это проблема при использовании библиотек Managed DirectX 1.1 в VS2005 или 2008. Microsoft перешла на работу с MDX2, а затем XNA, а не с Managed DirectX 1, поэтому не надейтесь слишком много на патч.
Легкое обходное решение - отключить обработку LoaderLock Exception при отладке этого решения. Это не должно иметь никакого реального влияния на программу, так как эта ошибка появляется только в среде отладки.
Чтобы отключить функцию "Отладка" → "Исключения" → "Помощники для отладки" и снимите флажок "LoaderLock".
Дополнительная информация здесь: http://vivekthangaswamy.blogspot.com/2006/11/loaderlock-was-detected-error-when.html
Ответ 9
использовать MCI
его прост в использовании и работает даже на NT:
using System.Runtime.InteropServices;
[DllImport("winmm.dll")]
public static extern int mciSendString(string lpstrCommand, StringBuilder lpstrReturnString, int uReturnLength, int hwndCallback);
[DllImport("winmm.dll")]
private static extern int mciGetErrorString(int l1, StringBuilder s1, int l2);
string cmd = "open " + strFile + " alias video";
StringBuilder mssg = new StringBuilder(255);
int h = mciSendString(cmd, null, 0, 0); // open video at mci
int i = mciSendString("set video time format ms", null, 0, 0); // set time format, you can see other formats at link above
int j = mciSendString("status video length", mssg, mssg.Capacity, 0); //get video length into mssg
Console.WriteLine(mssg.ToString());
int m = mciSendString("close video", null, 0, 0); //close video
Ответ 10
Кажется, что я публикую, что я пробовал, так поздно. Надеюсь, это поможет кому-то.
Я попытался немного увеличить длину видео, поделив компонент Windows Media Player.
Следующий фрагмент кода может помочь вам:
using WMPLib;
// ...your code here...
var player = new WindowsMediaPlayer();
var clip = player.newMedia(filePath);
Console.WriteLine(TimeSpan.FromSeconds(clip.duration));
и не забудьте добавить ссылку wmp.dll
, которая будет присутствует в папке System32
.
Ответ 11
Вы можете использовать нашу оболочку для ffprobe Alturos.VideoInfo. Вы можете использовать его, просто установив пакет nuget
. Также требуется двоичный файл ffprobe.
PM> install-package Alturos.VideoInfo
пример
var videoFilePath = "myVideo.mp4";
var videoAnalyer = new VideoAnalyzer("ffprobe.exe");
var analyzeResult = videoAnalyer.GetVideoInfo(videoFilePath);
//Video length
var duration = analyzeResult.VideoInfo.Format.Duration;