导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2020/3/22 12:54:28
标题:
加入我的收藏
楼主:
这几天做个Win64程序,用Firemonkey做。 有一系列视频文件,需要从每个视频文件中截取一幅画,来作为视频文件列表的列表项图片,有点类似Windows资源管理器中浏览视频文件时的缩略图效果。希望直接用从视频文件中截取画面,而不是播放出来后截屏的方式。 请教大家有什么实现方法? 我看了PasLibVlc,好像得Play后,才能截取。
----------------------------------------------
-
作者:
2020/3/22 13:28:20
1楼:
那就调用ffmpeg
----------------------------------------------
作者:
hsj (hsj)
★☆☆☆☆
-
盒子活跃会员
2020/3/23 16:10:02
2楼:
不需要播放吧,你看看苦力的ffvcl
----------------------------------------------
qq:171833017,靖源软件http://www.dxmylove.com
作者:
2020/3/24 9:15:22
3楼:
谢谢两位,我先试试看直接调用ffmpeg.exe来生成
----------------------------------------------
-
作者:
hsj (hsj)
★☆☆☆☆
-
盒子活跃会员
2020/3/24 11:06:55
4楼:
很早之前写的,自己都不记得了 FFDecoder := TFFDecoder.Create(nil); try if not FFDecoder.AVLibLoaded then begin if not FFDecoder.LoadAVLib(GetCurrentPath + 'plugin') then begin msg := FFDecoder.LastErrMsg; Exit; end; end; if not FFDecoder.LoadFile(fn) then begin msg := '文件打开错误' + #13#10 + fn + #13#10 + FFDecoder.LastErrMsg; Exit; end; apts := Round(0.5 * mi.PlayTime); if FFDecoder.Seek(apts) or FFDecoder.Seek(APTS, [sfBackward]) or FFDecoder.Seek(APTS, [sfAny]) then begin FFDecoder.Decode; bmp := TBitmap.Create; try FFDecoder.CopyToBitmap(bmp); BmpFitStretch(bmp, ThumbWidth, ThumbHeight); waterfn := getcurrentpath + 'images\mp4demo.png'; JyGetImageWater(bmp, waterfn, x, y); bmp2gif(bmp, newfn); finally bmp.Free; end; end else begin msg := 'mp4缩略图获取失败!' + FFDecoder.LastErrMsg; Exit; end; Application.ProcessMessages; finally FFDecoder.Free; end;
----------------------------------------------
qq:171833017,靖源软件http://www.dxmylove.com
作者:
2020/3/24 17:08:02
5楼:
嗯,下了个ffvcl lite版,发现生成的图片加了水印。再折腾折腾。
----------------------------------------------
-
作者:
2020/3/25 16:03:42
6楼:
其实也是要解码播放的。 现在的视频,大多是 264 或 MPEG4 类似的格式,也就是帧间压缩。不可能不解码单独从文件里面取出一帧数据,就能得到画面。 视频文件里面的一帧数据,是不能单独解压缩的,除非刚好是关键帧。其它的帧,都要参考前面的帧或者参考关键帧才能解码为图片。 所以,如果你有办法搜到关键帧,单独提取出来解码为图片。要么,不如直接播放解码。 直接播放解码,如果是 WINDOWS 底下,玩 Delphi 的话,很简单,用那套 Dspack 控件,加上网上开源的 FFDshow 也就是一套将 FFMPEG 的解码库封装为 DirectShow 的 DirectShow Filter,安装到你的电脑里面,用 Dspack 控件去调用。 上述玩法我这里写不了太详细。有需要的话,我再写详细教程。 Dspack 官方只支持到 D7 没有再更新。我修改了一点支持到新版 Delphi,我的 CSDN 下载资源里面有。我也放到我的 github 里面了。
----------------------------------------------
-
作者:
2020/3/25 17:09:28
7楼:
支持支持 把DELPHI当作爱好了,在线培训系统http://www.nxexam.com
----------------------------------------------
wj2310
作者:
2020/4/5 12:19:45
9楼:
@codecoolie,苦力兄,你应该是加了水印的。 我直接编译Lite包里附的PlayerDemo程序,点击里面的Capture按钮,截的图如下: 另外,Lite版的TFFPlayer的Seek()方法好像是屏蔽了吧?设不了播放进度跳转。
----------------------------------------------
-
作者:
2020/4/5 19:20:14
10楼:
FFDecoder确实没有加水印。我之前是用FFPlayer试的。
----------------------------------------------
-
作者:
2021/11/12 20:31:07
12楼:
@pcplayer 我想用DSPack 做个摄像头监控(录制声音图像和拍照),目前参照DSPack的例程videocap做了。由于自己真的太不懂这个东西了,遇到麻烦,百度了好几天都无法克服。 2个问题: 一是录制视频ASF格式声音和视频效果不理想。用AVI格式不错,但是太大了,如何将视频压缩成WMV或MP4呢? 二是在保存的视频叠中加上录制的日期时间。 我百度说是自己写 Filter文件,但是我百度好几天,没有这样的资料。不怕笑话,用D10.2我连AX都编译不了。更别谈如何自己调用了。 能告诉我该怎么做吗?我就是个小白,期待你的回音!!先谢了327846439@QQ.com
----------------------------------------------
-
作者:
2021/11/12 22:53:50
13楼:
唉,写了一大篇有关 DirectShow 的,又是非法字符。懒得找哪个字符非法了,贴我的博客里面去。
----------------------------------------------
-
作者:
2021/11/12 23:18:53
14楼:
写好博客了: https://blog.csdn.net/pcplayer/article/details/121297993
----------------------------------------------
-
作者:
2021/11/13 1:38:20
15楼:
另外,关于 DsPack 这个控件: 1. 这个控件原本是开源的; 2. 原作者最后的版本,停留在对 D7 的支持。 3. 本人修改了一下,可以支持 Delphi 的更高的版本。 本人修改后的控件源代码:https://github.com/pcplayer/Dspack
----------------------------------------------
-
作者:
2021/11/13 2:08:23
16楼:
楼上够勤奋的,说写就写,说干就干啊
----------------------------------------------
只有偏执狂才能生存!
作者:
2021/11/13 12:29:41
17楼:
@pcplayer,谢谢了,看完你的文章,我更迷糊了。太高深了啊。
----------------------------------------------
-
作者:
2021/11/13 16:21:07
18楼:
@pcplayer,及坛友帮看下。 DSPack 做个摄像头监控,两个问题: 1.如何压缩AVI视频文件(或者保存其他的清楚点的文件格式,ASF格式就不用了),这样的文件太大了,硬盘受不了。 2.能否在保存的视频上叠加上录制的“年月日时分秒”字幕。 谢谢了!!!文件夹里有个我找到的叠加记录时间的部分代码,我就是个小白,我真弄不明白。
----------------------------------------------
-
作者:
2021/11/13 20:43:06
19楼:
@17 楼:有了基本概念,你再去看 DSPack 的 Demo 就比较容易知道它在干什么。 1. 压缩,你就是要找一个编码器。你可以看看你自己电脑里面有没有安装编码器。一般是 H.264 的;或者你安装一下 FFDShow 那个开源的的东西,安装完后看看电脑里面有没有。 看的办法,就是拖一个 Dspack 的 Filter 到屏幕上,然后点它的属性,它会枚举显示你电脑里面安装过的各种 Filter 出来,找找其中有没有编码器。 或者用那个 DirectShow 官方带的工具 GraphEdit。 2. 叠加字幕:如果你想直接在图像上叠加字幕,其实就是把字符,作为图片,叠加到视频的一帧上。视频的每一帧,在编码压缩前,其实就是一个图片。类似用代码把一个图片叠到另一个图片上。当然,如果这个功能要自己实现,就要自己写一个 Filter,类似的 Filter,DsPack 带的 Demo 里面有。 另外一种叠加字幕的方式,其实是你自己拿文字,叠加到最终播放的时候的屏幕上。当然,这个字幕文件,就要自己另外做,它就是一个按时间的 TEXT 文件,到了对应的时间,把这个 TEXT 文件里面对应的字符串取出来,叠加到最终播放的屏幕上。 要把字符串叠加到最终播放的屏幕上,使用 DsPack 带的两个最终显示的 Filter 里面的其中一个,具体控件名字我不记得了,作为 Filter 它的名字大概是 Render,也就是控件里面拖到屏幕上是一个播放器窗口的那个控件。这样的控件有2个,其中一个,开源实现在最终显示的时候叠加字幕。
----------------------------------------------
-
作者:
2021/11/13 20:51:14
20楼:
查了一下我以前的记录,保存为 MP4,这里有一个开源的 Filter: http://www.gdcl.co.uk/mpeg4/ 这个是可以直接拿来用的。
----------------------------------------------
-
作者:
2021/11/13 21:05:15
21楼:
查了一下我以前的代码: FVMRBitmap: TVMRBitmap; FVMRBitmap := TVMRBitmap.Create(VideoWindow2); //这个 VideoWindow2 就是拖到界面上的 DsPack 的播放器窗口,它本质也是一个 Filter。设置它的属性,取 VMR9 然后,以下代码可以把字符串画到视频窗口里面,也就是外挂字幕: procedure TFmIr264Decoder.DrawOSD(const AWidth, AHeight, AFontSize: Integer; const AFontColor, BGColor: TColor; const OSD: string); begin //画OSD在视频上。可以用来显示一些提示。 with FVMRBitmap, Canvas do begin LoadEmptyBitmap(AWidth, AHeight ,pf24bit, BGColor); Source := FVMRBitmap.Canvas.ClipRect; Options := FVMRBitmap.Options + [vmrbSrcColorKey]; ColorKey := BGColor; Brush.Color := BGColor; Font.Color := AFontColor; //Font.Style := [fsBold]; Font.Size := AFontSize; //30; Font.Name := 'Arial'; TextOut(0,0,OSD); DrawTo(0,0,1,1,0.5); end; end;
----------------------------------------------
-
作者:
2021/11/13 21:59:19
22楼:
@pcplayer 非常感谢你的回答。主要一是我不知道怎么写这个 Filter,惭愧啊。太难搞懂了。翻了一天的百度,也没弄个明白。Dspack 自带的 Filter,我也看了,有人说参考例程NullIP写个叠加时间的字幕,唉,我在看,构造和原理不懂。 二是自己写的Filter的AX文件,如何被Dspack调用呢,实在是搞不明白啊,DEMO里一个这样的例程也没有。怎么和其他的Filter合并一起调用,搞不明白,网上基本没看到自己编写的AX的调用方法哦。
----------------------------------------------
-
作者:
2021/11/13 22:30:46
23楼:
1. 如果是外挂字幕,不需要写 Filter 了。 2. 录像为 MP4,也有现成的,我都把地址贴出来了。 总之完成你的任务不需要写 Filter 了。
----------------------------------------------
-
作者:
2021/11/13 22:53:54
23楼:
@pcplayer : 下载的 Dspack-master 不能编译通过,D10。。。 Dspack-master\src\DirectX9\DirectDraw.pas ******* [dcc32 Error] DirectDraw.pas(359): E2154 Type 'IDirectDrawSurface' needs finalization - not allowed in variant record ********** case Integer of 0: ( dwZDestConst : DWORD // Constant to use as Z buffer for dest ); 1: ( lpDDSZBufferDest : PDirectDrawSurface; // Surface to use as Z buffer for dest
----------------------------------------------
阳光总在
作者:
2021/11/13 23:13:26
24楼:
你在哪里下载的? 以前的 Dspack 包含了它要用到的 DirectX 的文件,主要是 DirectShow9.pas。我不记得有 DirectDraw.pas 新版的 Delphi (XE 以后),已经包含了 DirectShow9.pas,所以要把 Dspack 原本的去掉。
----------------------------------------------
-
作者:
2021/11/13 23:26:04
25楼:
15 楼的帖子:本人修改后的控件源代码:https://github.com/pcplayer/Dspack 直接可以install Dspack in D1042, 但不能编译 demo
----------------------------------------------
阳光总在
作者:
2021/11/13 23:33:24
26楼:
哦。我只是修改了控件。每修改 Demo 你把 Demo 关于 DirectDraw 和 DirectShow 的都去掉,应该就可以了。
----------------------------------------------
-
作者:
2021/11/13 23:44:18
27楼:
谢谢楼上, 不过去掉后,不能编译,红色的地方更多了。。。 :) 可能Demo里面的D7的东西还在..
----------------------------------------------
阳光总在
作者:
2021/11/14 10:42:25
28楼:
@pcplayer 谢谢你深夜的回复。您再帮我看看怎么解决这个问题。谢谢了 GDCL Mpeg-4,我下载,DLL文件注册了,在控件"VideoSourceFilter. BaseFilter"选项上,我也选择上这个GDCL Mpeg-4了。 但是在下面的代码中:只能写出AVI或ASF,才可以输出视频,我如何调用压缩输出MP4呢? //这里的Tguid的格式里没有Mpeg-4或MP4哦,这里的"MEDIASUbTYPE"该如何设置呢 ,CapFName为视频输出路径。 SetOutputFileName(MEDIASUbTYPE_AVI, PWideChar(CapFName), multiplexer, Writer); //连接视频预览(VideoWindow) if VideoSourceFilter.BaseFilter.DataLength > 0 then RenderStream(@PIN_CATEGORY_PREVIEW, nil, VideoSourceFilter as IBaseFilter, SampleGrabber1 as IBaseFilter, VideoWindow as IBaseFilter); //连接视频捕获流 if VideoSourceFilter.FilterGraph <> nil then RenderStream(@PIN_CATEGORY_CAPTURE, nil, VideoSourceFilter as IBaseFilter, nil, multiplexer as IBaseFilter); //连接音频捕获流 if AudioSourceFilter.FilterGraph <> nil then RenderStream(nil, nil, AudioSourceFilter as IBaseFilter, nil, multiplexer as IBaseFilter);
----------------------------------------------
-
作者:
2021/11/14 10:56:53
29楼:
怎么设置Filter调用GDCL Mpeg-4能压缩输出MP4视频文件呢!!
----------------------------------------------
-
作者:
2021/11/14 20:18:38
30楼:
我试着拖一个新的Filter1,在它的BaseFilter里,我选上了GDCL Mpeg-4,代码改成下面这样,但是运行,只能扑捉到声音,没有图像,而把这句Filter1 as IbaseFilter 换成nil,就可以录AVI 的视频。怎么回事??? // Connect Video capture streams if VideoSourceFilter.FilterGraph <> nil then RenderStream(@PIN_CATEGORY_CAPTURE, nil, VideoSourceFilter as IBaseFilter,Filter1 as IbaseFilter , multiplexer as IBaseFilter);
----------------------------------------------
-
作者:
2021/11/15 17:40:05
31楼:
【if VideoSourceFilter.BaseFilter.DataLength > 0 then RenderStream(@PIN_CATEGORY_PREVIEW, nil, VideoSourceFilter as IBaseFilter, SampleGrabber1 as IBaseFilter, VideoWindow as IBaseFilter);】 这样的代码,就是连接各个 Filter。我前面的文章讲过所谓连接 Filter 的概念。 除了用代码连接,你可以在 GraphEdit 那个工具里面,可视化的拉线连接。你可以先用那个工具试试建立各种 Filter 之间的连接。没有问题的,再到自己的程序里面,用代码去连接。
----------------------------------------------
-
作者:
2021/11/16 8:26:04
32楼:
pcplayer,谢谢,我到今天才明白,这个FILTER不是随便组合的啊!研究中
----------------------------------------------
-
作者:
2021/11/16 13:35:54
33楼:
终于跑出来个WMV。声音也正常,不变音。谢谢pcplayer的大力帮助。
此帖子包含附件: 大小: 271.1K
----------------------------------------------
-
作者:
2021/11/17 18:07:34
34楼:
恭喜楼上。 这个 GraphEdit 就是图形化的连接 Filter 的工具。在这里测试成功后,你就可以在代码里面,用程序去连接这些 Filter 了。
----------------------------------------------
-
作者:
2021/11/17 18:07:57
35楼:
关于声音正常: 正常的一个媒体文件,每一帧,都有时间戳;里面的声音数据,也有时间戳。在 DirectShow 里面,为了达到声画同步,视频数据的播放节奏,以声音数据的时间戳为准。这样能保证声音的播放连续。
----------------------------------------------
-
作者:
2021/11/17 18:10:04
36楼:
至于你说才明白 Filter 不能随便组合,其实我前面的博客文章里面已经讲了啊。你前面是一个处理视频数据的 Filter 它输出视频数据,当然不能在后面接一个处理音频数据的 Filter,接上也没意义嘛。Filter 的 PIN 有个媒体类型的属性的,媒体类型不一致的,接不上去。
----------------------------------------------
-
作者:
2021/11/17 18:11:42
37楼:
写了一大段,还是有非法字符。还能不能好好讨论技术问题了
----------------------------------------------
-
作者:
2021/11/26 15:26:02
38楼:
@ pcplayer SetOutputFileName(MEDIASUbTYPE_Avi, PWideChar(CapFile), multiplexer, Writer); 这里的 AVI改为Asf录制的视频为什么声音会断断续续的,没声音的时间很长,如何克服呢??谢谢!!
----------------------------------------------
-
作者:
tiez (骑牛夜旅)
★☆☆☆☆
-
普通会员
2021/11/26 16:11:32
39楼:
解决了就可喜可贺啊。我原来是买了FFVCL的许可用了几年,挺好用的,学习一下也挺复杂的。主要是用来转实时码流或做显示用的,效果挺好加个特效加个屏显什么的。 还用过RVMedia,这个也挺好用,就是这两个我都没结合Firemonkey用过,不知道是什么效果了。 这两个都是可以在事件里取帧的,好像取的都是图元数据吧。
----------------------------------------------
-
作者:
2021/11/26 17:44:28
40楼:
38 楼: 1. 原理:不管什么视频文件,在建立一个 DirectShow 的 Graph 的时候,一开始进来的数据,必须经过一个叫做分离器的 Filter,把进来的数据分成视频数据和音频数据。这个 Filter 输出有两个PIN,一个输出视频,一个输出音频;音频数据输出 PIN后面接音频相关的 Filter; 2. 音像同步:DirectShow 默认拿声音的时间戳来做时间同步,这样能保证声音连续。保证声音连续的情况下,可能视频会慢或者快。 如果声音能播放出来,只是断续,可能需要看看哪里有和时间戳相关的代码需要改改。 另外一种可能,你用错了声音解码的 Filter。换个其它的 Filter 看看。 ---------- 39 楼:我罗嗦几句。如果玩 FFMPEG 非常熟悉,用它能做很多事情。但这个玩意也够复杂的,而且还是 C 代码的。 如果了解了 DirectShow,你会发现这个玩意其实比较简单。但它却是出了名的难,大概是因为即便是 MS 的官方资料,也没把它的概念讲清楚。 DirectShow 的问题是,MS 自己都放弃了。MS 新一代的媒体框架叫什么来着,我是没去研究。当然,这个新一代的媒体框架是架构在 DirectShow 框架上面的,大概就是为了让程序员使用框架更简单。 我看过 FireMonkey 的 MediaPlayer 的代码,在 Windows 上,它是基于 DirectShow 的。所以这个玩意应该还是可以继续用的。 DirectShow 有个好处是有很多别人做好的 Filter,可能你电脑里面安装了一个什么媒体程序(比如播放器)就带来了,你用它的 GraphEdit 工具就能看到。只要你电脑里面装过的,你就能使用,不需要有文档就能用。
----------------------------------------------
-
作者:
2021/11/28 16:42:00
41楼:
@ tiez 谢谢你的帮助。
----------------------------------------------
-