ファイルからメタデータを読み取ろうとしています。 Video-> Lengthプロパティのみが必要ですが、この情報を読み取る簡単な方法を見つけることができません。
これはエクスプローラーにデフォルトで表示されるため、かなり簡単だと思いましたが、予想よりもはるかに複雑に見えます。私が来た最も近いものは使用していました:
Microsoft.DirectX.AudioVideoPlayback.Video video = new Microsoft.DirectX.AudioVideoPlayback.Video(str);
double duration = video.Duration;
ただし、これはLoaderLock例外をスローし、対処方法がわかりません。
何か案は?
これらの詳細の多くはシェルによって提供されるため、COMライブラリ「MicrosoftShell Controls and Automation」(Shell32)への参照を追加し、Folder.GetDetailsOfメソッドを使用して拡張詳細を照会することでこれを行うことができます。
私は最近これを探していて、MSDN C#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だと思います)、クエリを実行する方がはるかに高速です。注:インデックスが変更できるかどうかについてはあまり調査していませんでした(疑わしいです)。そのため、辞書を使用しました。
これを見てくださいSO質問- C#/。NET用のソリッドFFmpegラッパー これはいくつかのffmpeg.Net実装にリンクしています。ffmpegはほとんどのビデオフォーマット/コーデックで動作します。そうすれば、コーデックがマシンにインストールされていることを心配する必要はありません。
または、 https://mediaarea.net/en/MediaInfo をご覧ください。
ミカエルの投稿にコメントしただけなのですが、まだ十分な担当者がいません。コーデックをインストールする必要がないように、ffmpegの使用について彼に同意します。 「ffmpeg-iyour_filename」の出力を解析するだけで、長さなどのビデオに関する情報をダンプできます。
使用しているコーデックがわかりませんが、一部のコンテナは実際にはメタデータに期間を保存しません(期間が不明なため、これはストリーミングコンテナで一般的です)。 ffmpegがこれをどのように処理するかはわかりませんが、どういうわけかそれを見つけているようです(おそらくタイムコードのためにファイル全体を解析することによって)。
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);
}
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;
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;
}
}
Win RtAppまたはMetroC#でビデオファイルの長さを取得する:
StorageFile videoFile;
videoFile = await StorageFile.GetFileFromPathAsync(VIDEO_PATH_HERE);
Windows.Storage.FileProperties.VideoProperties x = await videoFile.Properties.GetVideoPropertiesAsync();
var videoDuration = x.Duration;
MediaInfo は、その目的に最適なオープンソースライブラリです(DLLはライセンスされたLGPLです)。ダウンロードパッケージには、C#のサンプルアプリケーションが含まれています(Developers\Project\MSCS\Example
)
使いやすく、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
私が試したことを投稿しているようですので、遅くなりました。それが誰かを助けることを願っています。
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
の参照を追加することを忘れないでください。
小さなビデオプレビューアプリでも同じ問題が発生しました。
問題は、Managed DebuggingAssistantsです。これは、VS2005または2008でManaged DirectX 1.1ライブラリを使用する場合の問題です。Microsoftは、Managed DirectX 1ではなくMDX2、次にXNAに重点を置いているため、パッチをあまり期待しないでください。
簡単な回避策は、そのソリューションのデバッグ中にLoaderLock例外処理を無効にすることです。このエラーはデバッグ環境でのみ表示されるため、これはプログラムに実際の影響を与えることはありません。
無効にするには、[デバッグ]-> [例外]-> [マネージドデバッグアシスタント]に移動し、LoaderLockのチェックを外します。
詳細はこちら: http://vivekthangaswamy.blogspot.com/2006/11/loaderlock-was-detected-error-when.html