如何从WMV视频创建缩略图

3
我希望在网站上列出视频的缩略图,想要从视频中获取单个帧(从特定时间)并将其显示为缩略图。使用 .Net(C# 或 VB)可以实现吗?
1个回答

2
是的,这是可能的。您需要使用DirectShow.NET。我找到了这个链接很有用。
编辑:
好的,看起来自从我使用它以来库已经改变了...该死的开源 :)
我刚刚翻译成以下代码并测试,对我来说运行良好(请注意,它假定在c:\aaa中有一个wmv文件名为C4.wmv,并且输出将进入c:\aaa\out.bmp)。
IGraphBuilder graphbuilder = (IGraphBuilder)new FilterGraph();
      ISampleGrabber samplegrabber = (ISampleGrabber) new SampleGrabber();
      graphbuilder.AddFilter((IBaseFilter)samplegrabber, "samplegrabber");

      AMMediaType mt = new AMMediaType();
      mt.majorType = MediaType.Video;
      mt.subType = MediaSubType.RGB24;
      mt.formatType = FormatType.VideoInfo;
      samplegrabber.SetMediaType(mt);

      int hr = graphbuilder.RenderFile("C:\\aaa\\c4.wmv", null);

      IMediaEventEx mediaEvt = (IMediaEventEx)graphbuilder;
      IMediaSeeking mediaSeek = (IMediaSeeking)graphbuilder;
      IMediaControl mediaCtrl = (IMediaControl)graphbuilder;
      IBasicAudio basicAudio = (IBasicAudio)graphbuilder;
      IVideoWindow videoWin = (IVideoWindow)graphbuilder;

      basicAudio.put_Volume(-10000);
      videoWin.put_AutoShow(OABool.False);

      samplegrabber.SetOneShot(true);
      samplegrabber.SetBufferSamples(true);

      long d = 0;
      mediaSeek.GetDuration(out d);
      long numSecs = d / 10000000;

      long secondstocapture = (long)(numSecs * 0.10f);


      DsLong rtStart, rtStop;
      rtStart = new DsLong(secondstocapture * 10000000);
      rtStop = rtStart;
      mediaSeek.SetPositions(rtStart, AMSeekingSeekingFlags.AbsolutePositioning, rtStop, AMSeekingSeekingFlags.AbsolutePositioning);

      mediaCtrl.Run();
      EventCode evcode;
      mediaEvt.WaitForCompletion(-1, out evcode);

      VideoInfoHeader videoheader = new VideoInfoHeader();
      AMMediaType grab = new AMMediaType();
      samplegrabber.GetConnectedMediaType(grab);
      videoheader =
      (VideoInfoHeader)Marshal.PtrToStructure(grab.formatPtr,
      typeof(VideoInfoHeader));


      int width = videoheader.SrcRect.right;
      int height = videoheader.SrcRect.bottom;
      Bitmap b = new Bitmap(width, height, PixelFormat.Format24bppRgb);

      uint bytesPerPixel = (uint)(24 >> 3);
      uint extraBytes = ((uint)width * bytesPerPixel) % 4;
      uint adjustedLineSize = bytesPerPixel * ((uint)width + extraBytes);
      uint sizeOfImageData = (uint)(height) * adjustedLineSize;


      BitmapData bd1 = b.LockBits(new Rectangle(0, 0, width, height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb);
      int bufsize = (int)sizeOfImageData;
      int n = samplegrabber.GetCurrentBuffer(ref bufsize, bd1.Scan0);
      b.UnlockBits(bd1);
      b.RotateFlip(RotateFlipType.RotateNoneFlipY);
      b.Save("C:\\aaa\\out.bmp");
      Marshal.ReleaseComObject(graphbuilder);
      Marshal.ReleaseComObject(samplegrabber);

请注意,DirectShow在某种程度上处于悬而未决的状态...微软公司建议您使用Media Foundation。我是一位老派的DirectX程序员,现在基本没有使用了。


你好,我引用了DirectShowLib-2005.dll,但是在你给我链接的示例代码的第二行卡住了 :) Type comtype = Type.GetTypeFromCLSID( Clsid.FilterGraph );ClsId应该是什么? - Michel
嗯,我几乎不敢问...我更新了我的相机附带的软件,现在GRMBL软件不再允许我导出到WMV,而只能导出到它的本地格式:MP4。我试图理解代码,使其也适用于MP4文件(因为它在MP4文件上崩溃),但我真的不知道该怎么做。你能帮我解决这个问题吗? - Michel
我对MPEG-4和DS的经验不是很丰富,恐怕无法提供太多帮助。据我所知,DS默认不支持MPEG-4格式,需要安装第三方滤镜(快速谷歌可以找到这个http://www.softpedia.com/progDownload/FFDShow-MPEG-Video-Decoder-Download-5527.html 但我没有使用过)。我的大部分MPEG-4经验来自于hackign ffmpeg以构建转码器。我建议您实际查看ffmpeg作为命令行解决方案,您可以在服务器端使用它来创建缩略图(我在一些非常大的视频网站上非常成功地使用了它)。 - Gray Area

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接