J'ai un windowsservice censé générer des empreintes de vidéos. Pour ce faire, j'essaie d'utiliser la classe MediaElement (https://msdn.microsoft.com/en-us/library/system.windows.controls.mediaelement(v=vs.110).aspx). Pour déclencher des événements lors de l'ouverture de médias, cet élément doit être dans un visualtree. Est-il possible de simuler ou de simuler un arbre visuel? Editer: J'utilise maintenant MediaPlayer au lieu de MediaElements mais je ne peux pas compter sur les événements car ils ne sont pas lancés.C#: est-il possible de générer ou de truquer un arbre visuel dans un service?
code mis à jour
public class Mp4ThumbnailExtractor : IDisposable
{
private ManualResetEvent waitHandle;
private TimeSpan mediaOpenTimeout;
public TimeSpan Time { get; set; }
= TimeSpan.Parse("00:00:30");
public TimeSpan FallbackTime { get; set; }
= TimeSpan.Parse("00:00:10");
public int Height { get; set; }
= 400;
public int Width { get; set; }
= 400;
public int Dpi { get; set; }
= 96;
public Mp4ThumbnailExtractor()
{
waitHandle = new ManualResetEvent(false);
mediaOpenTimeout = TimeSpan.Parse("00:00:15");
}
public MemoryStream CreateThumbnail(string videoPath)
{
MemoryStream memory = new MemoryStream();
Uri sourceUri = new Uri(videoPath);
MediaPlayer media = new MediaPlayer();
media.MediaOpened += Media_MediaOpened;
media.ScrubbingEnabled = true;
try
{
media.Open(new Uri(videoPath));
//TODO: media.opened event will not get fired
Thread.Sleep(mediaOpenTimeout);
waitHandle.Set();
//15sec timeout for loading the media
if (waitHandle.WaitOne(mediaOpenTimeout))
{
SetPosition(media);
//TODO: this is bad...
Thread.Sleep(2000);
DrawingVisual dv = new DrawingVisual();
DrawingContext dc = dv.RenderOpen();
dc.DrawVideo(media, new Rect(0, 0, Width, Height));
dc.Close();
RenderTargetBitmap bmp = new RenderTargetBitmap(Width, Height, Dpi, Dpi, PixelFormats.Pbgra32);
bmp.Render(dv);
JpegBitmapEncoder encoder = new JpegBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bmp));
encoder.Save(memory);
memory.Seek(0, SeekOrigin.Begin);
}
else
{
throw new Exception($"Unable to open media '{videoPath}' in '{mediaOpenTimeout}'");
}
}
finally
{
media.Close();
}
return memory;
}
private void SetPosition(MediaPlayer player)
{
if (player.NaturalDuration.HasTimeSpan)
{
TimeSpan naturalTime = player.NaturalDuration.TimeSpan;
if (naturalTime < Time)
{
if (naturalTime > FallbackTime)
{
player.Position = FallbackTime;
}
}
else
{
player.Position = Time;
}
}
}
private void Media_MediaOpened(object sender, EventArgs e)
{
waitHandle.Set();
}
public void Dispose()
{
waitHandle.Dispose();
}
}
MediaElement est un élément visuel. Pourquoi ne pas utiliser [MediaPlayer] (https://msdn.microsoft.com/en-us/library/system.windows.media.mediaplayer (v = vs.110) .aspx) à la place? – icebat
MediaPlayer est en mesure d'obtenir des captures d'écran mais l'événement MediaOpened n'est pas déclenché et le réglage de la Positition fonctionne 2 fois sur 3. J'ai ajouté un Thread.Sleep codé en dur (150000); waitHandle.Set(); avant waitHandle.Wait. Ce n'est pas une solution fiable –