私が開発したデジタルサイネージuwpアプリでも同様の要件がありました。ウェブの検索方法UWPでは、保護ポリシーのためにメディア要素のスクリーンショットを直接取得することはできません(たとえば、DRMなしのビデオファイルのすべてのフレームをキャプチャする小さなアプリケーションを作成することができます管理)。
私は回避策を思いつきました:ビデオファイルをローカルに持っているので、特定のポイントで1つのフレームを抽出し、画面にレンダリングされたビデオと同じサイズのディスクに保存できます(このようにして、後で使用するフレームの完全な画像)。これを行うには、私は、この関数を書いた:
private async Task<string> Capture(StorageFile file, TimeSpan timeOfFrame, Size imageDimension)
{
if (file == null)
{
return null;
}
//Get FrameWidth & FrameHeight
List<string> encodingPropertiesToRetrieve = new List<string>();
encodingPropertiesToRetrieve.Add("System.Video.FrameHeight");
encodingPropertiesToRetrieve.Add("System.Video.FrameWidth");
IDictionary<string, object> encodingProperties = await file.Properties.RetrievePropertiesAsync(encodingPropertiesToRetrieve);
uint frameHeight = (uint)encodingProperties["System.Video.FrameHeight"];
uint frameWidth = (uint)encodingProperties["System.Video.FrameWidth"];
//Get image stream
var clip = await MediaClip.CreateFromFileAsync(file);
var composition = new MediaComposition();
composition.Clips.Add(clip);
var imageStream = await composition.GetThumbnailAsync(timeOfFrame, (int)frameWidth, (int)frameHeight, VideoFramePrecision.NearestFrame);
//Create BMP
var writableBitmap = new WriteableBitmap((int)frameWidth, (int)frameHeight);
writableBitmap.SetSource(imageStream);
//Get stream from BMP
string mediaCaptureFileName = "IMG" + Guid.NewGuid().ToString().Substring(0, 4) + ".jpg";
var saveAsTarget = await CreateMediaFile(mediaCaptureFileName);
Stream stream = writableBitmap.PixelBuffer.AsStream();
byte[] pixels = new byte[(uint)stream.Length];
await stream.ReadAsync(pixels, 0, pixels.Length);
using (var writeStream = await saveAsTarget.OpenAsync(FileAccessMode.ReadWrite))
{
var encoder = await BitmapEncoder.CreateAsync(BitmapEncoder.JpegEncoderId, writeStream);
encoder.SetPixelData(
BitmapPixelFormat.Bgra8,
BitmapAlphaMode.Premultiplied,
(uint)writableBitmap.PixelWidth,
(uint)writableBitmap.PixelHeight,
96,
96,
pixels);
await encoder.FlushAsync();
using (var outputStream = writeStream.GetOutputStreamAt(0))
{
await outputStream.FlushAsync();
}
}
return saveAsTarget.Name;
}
この関数は、イメージとしてディスクにフレームを保存し、彼の名を返します。 私のアプリケーションでは、より多くの「ウィジェット」(画像付きのもの、ビデオ付きのもの)がありましたので、この関数を使用してビデオフレームを取得し、同じサイズのキャンバスの上に新しい画像を配置しましたZ-インデックスRenderTargetBitmap
を使用して最終的なスクリーンショットを撮る。 これはきれいな解決策ではありませんが、RenderTargetBitmap
MediaElementを考慮しない場合の回避策でした。
編集:私は自分のアプリケーション内の内部関数への参照を忘れてしまった はので、私は前のコードをcanghedとラインvar file = await _mediaEngine.CreateMediaFile($"{Guid.NewGuid().ToString()}.jpg");
は今var file = await CreateMediaFile($"{Guid.NewGuid().ToString()}.jpg");
非同期関数CreateMediaFile(文字列のファイル名)である単に作成ディスク上の新しいファイル:
public async Task<StorageFile> CreateMediaFile(string filename)
{
StorageFolder _mediaFolder = KnownFolders.PicturesLibrary;
return await _mediaFolder.CreateFileAsync(filename);
}
こんにちはAgostini、ありがとうございます。 _mediaEngineが認識されなくなるまで滑らかになります! –
Ops!申し訳ありません...私はその参照を逃す!私は1分で私の答えを編集するつもりです... –
@MgBhadurudeen私は正しいコードで私の答えを更新しました。今は期待どおりに動作するはずです。お知らせ下さい! –