2017-08-28 8 views
0

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(); 
    } 
} 
+1

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

+0

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 –

Répondre

1

MediaElement est essentiellement un contrôle visuel pour l'hébergement de contenu média:

Représente un contrôle qui contient des données audio et/ou vidéo

Vous avez besoin d'une interface utilisateur -less MediaPlayer. N'oubliez pas d'appeler Open méthode ou MediaOpened ne tirera pas.

+0

Je suis maintenant capable de capturer des écrans mais les événements ne fonctionneront pas. J'ai maintenant 2 retards harcodés pour faire fonctionner le code (pour la plupart des cas, mais pas fiable, le réglage de la position aussi un peu peu fiable) –