DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: chnifo
今日帖子: 50
在线用户: 16
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2020/3/22 12:54:28
标题:
如何从视频文件中截取一幅画面? 浏览:1530
加入我的收藏
楼主: 这几天做个Win64程序,用Firemonkey做。
有一系列视频文件,需要从每个视频文件中截取一幅画,来作为视频文件列表的列表项图片,有点类似Windows资源管理器中浏览视频文件时的缩略图效果。希望直接用从视频文件中截取画面,而不是播放出来后截屏的方式。
请教大家有什么实现方法?

我看了PasLibVlc,好像得Play后,才能截取。
----------------------------------------------
-
作者:
男 xuchuantao (暗黑天使) ▲▲▲▲▲ -
注册会员
2020/3/22 13:28:20
1楼: 那就调用ffmpeg
----------------------------------------------
按此在新窗口浏览图片
作者:
男 hsj (hsj) ★☆☆☆☆ -
盒子活跃会员
2020/3/23 16:10:02
2楼: 不需要播放吧,你看看苦力的ffvcl
----------------------------------------------
qq:171833017,靖源软件http://www.dxmylove.com
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
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
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2020/3/24 17:08:02
5楼: 嗯,下了个ffvcl lite版,发现生成的图片加了水印。再折腾折腾。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2020/3/25 16:03:42
6楼: 其实也是要解码播放的。

现在的视频,大多是 264 或 MPEG4 类似的格式,也就是帧间压缩。不可能不解码单独从文件里面取出一帧数据,就能得到画面。

视频文件里面的一帧数据,是不能单独解压缩的,除非刚好是关键帧。其它的帧,都要参考前面的帧或者参考关键帧才能解码为图片。

所以,如果你有办法搜到关键帧,单独提取出来解码为图片。要么,不如直接播放解码。

直接播放解码,如果是 WINDOWS 底下,玩 Delphi 的话,很简单,用那套 Dspack 控件,加上网上开源的 FFDshow 也就是一套将 FFMPEG 的解码库封装为 DirectShow 的 DirectShow Filter,安装到你的电脑里面,用 Dspack 控件去调用。

上述玩法我这里写不了太详细。有需要的话,我再写详细教程。

Dspack 官方只支持到 D7 没有再更新。我修改了一点支持到新版 Delphi,我的 CSDN 下载资源里面有。我也放到我的 github 里面了。
----------------------------------------------
-
作者:
男 wj2310 (wj2310) ★☆☆☆☆ -
注册会员
2020/3/25 17:09:28
7楼: 支持支持









把DELPHI当作爱好了,在线培训系统http://www.nxexam.com
----------------------------------------------
wj2310
作者:
男 codecoolie (CodeCoolie) ▲▲▲▲▲ -
注册会员
2020/4/4 23:57:05
8楼: 呃,简化版的 FFDecoder 我没加水印啊,难道我记错了? FFPlayer 播放截图好像加了水印。
----------------------------------------------
FFmpeg for Delphi http://www.CCAVC.com http://www.DelphiFFmpeg.com
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2020/4/5 12:19:45
9楼: @codecoolie,苦力兄,你应该是加了水印的。
我直接编译Lite包里附的PlayerDemo程序,点击里面的Capture按钮,截的图如下:

按此在新窗口浏览图片

另外,Lite版的TFFPlayer的Seek()方法好像是屏蔽了吧?设不了播放进度跳转。
----------------------------------------------
-
作者:
男 szyourname (szyourname) ★☆☆☆☆ -
盒子活跃会员
2020/4/5 19:20:14
10楼: FFDecoder确实没有加水印。我之前是用FFPlayer试的。
----------------------------------------------
-
作者:
男 codecoolie (CodeCoolie) ▲▲▲▲▲ -
注册会员
2020/4/17 23:18:18
11楼: 简化版阉割的功能见控件包内的文本说明

如果用demo的话,遇到阉割的功能调用,会有相应log输出
----------------------------------------------
FFmpeg for Delphi http://www.CCAVC.com http://www.DelphiFFmpeg.com
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
2021/11/12 20:31:07
12楼: @pcplayer 我想用DSPack 做个摄像头监控(录制声音图像和拍照),目前参照DSPack的例程videocap做了。由于自己真的太不懂这个东西了,遇到麻烦,百度了好几天都无法克服。
2个问题:
一是录制视频ASF格式声音和视频效果不理想。用AVI格式不错,但是太大了,如何将视频压缩成WMV或MP4呢?
二是在保存的视频叠中加上录制的日期时间。
我百度说是自己写 Filter文件,但是我百度好几天,没有这样的资料。不怕笑话,用D10.2我连AX都编译不了。更别谈如何自己调用了。
能告诉我该怎么做吗?我就是个小白,期待你的回音!!先谢了327846439@QQ.com
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/12 22:53:50
13楼: 唉,写了一大篇有关 DirectShow 的,又是非法字符。懒得找哪个字符非法了,贴我的博客里面去。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/12 23:18:53
14楼: 写好博客了:

https://blog.csdn.net/pcplayer/article/details/121297993
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/13 1:38:20
15楼: 另外,关于 DsPack 这个控件:

1. 这个控件原本是开源的;
2. 原作者最后的版本,停留在对 D7 的支持。
3. 本人修改了一下,可以支持 Delphi 的更高的版本。

本人修改后的控件源代码:https://github.com/pcplayer/Dspack
----------------------------------------------
-
作者:
男 nevergrief (孤独骑士) ★☆☆☆☆ -
盒子活跃会员
2021/11/13 2:08:23
16楼: 楼上够勤奋的,说写就写,说干就干啊
----------------------------------------------
只有偏执狂才能生存!
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
2021/11/13 12:29:41
17楼: @pcplayer,谢谢了,看完你的文章,我更迷糊了。太高深了啊。
----------------------------------------------
-
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
2021/11/13 16:21:07
18楼: @pcplayer,及坛友帮看下。
DSPack 做个摄像头监控,两个问题:
1.如何压缩AVI视频文件(或者保存其他的清楚点的文件格式,ASF格式就不用了),这样的文件太大了,硬盘受不了。
2.能否在保存的视频上叠加上录制的“年月日时分秒”字幕。
谢谢了!!!文件夹里有个我找到的叠加记录时间的部分代码,我就是个小白,我真弄不明白。
此帖子包含附件:jljaaj_2021111316217.zip 大小:52.8K
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
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个,其中一个,开源实现在最终显示的时候叠加字幕。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/13 20:51:14
20楼: 查了一下我以前的记录,保存为 MP4,这里有一个开源的 Filter:

http://www.gdcl.co.uk/mpeg4/

这个是可以直接拿来用的。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
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;
----------------------------------------------
-
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
2021/11/13 21:59:19
22楼: @pcplayer  非常感谢你的回答。主要一是我不知道怎么写这个 Filter,惭愧啊。太难搞懂了。翻了一天的百度,也没弄个明白。Dspack 自带的 Filter,我也看了,有人说参考例程NullIP写个叠加时间的字幕,唉,我在看,构造和原理不懂。
二是自己写的Filter的AX文件,如何被Dspack调用呢,实在是搞不明白啊,DEMO里一个这样的例程也没有。怎么和其他的Filter合并一起调用,搞不明白,网上基本没看到自己编写的AX的调用方法哦。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/13 22:30:46
23楼: 1. 如果是外挂字幕,不需要写 Filter 了。

2. 录像为 MP4,也有现成的,我都把地址贴出来了。

总之完成你的任务不需要写 Filter 了。
----------------------------------------------
-
作者:
男 ww1000 (Delphis) ▲▲▲▲△ -
注册会员
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
----------------------------------------------
阳光总在
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/13 23:13:26
24楼: 你在哪里下载的?

以前的 Dspack 包含了它要用到的 DirectX 的文件,主要是 DirectShow9.pas。我不记得有 DirectDraw.pas

新版的 Delphi (XE 以后),已经包含了 DirectShow9.pas,所以要把 Dspack 原本的去掉。
----------------------------------------------
-
作者:
男 ww1000 (Delphis) ▲▲▲▲△ -
注册会员
2021/11/13 23:26:04
25楼: 15 楼的帖子:本人修改后的控件源代码:https://github.com/pcplayer/Dspack

直接可以install Dspack in D1042, 但不能编译 demo
----------------------------------------------
阳光总在
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/13 23:33:24
26楼: 哦。我只是修改了控件。每修改 Demo

你把 Demo 关于 DirectDraw 和 DirectShow 的都去掉,应该就可以了。
----------------------------------------------
-
作者:
男 ww1000 (Delphis) ▲▲▲▲△ -
注册会员
2021/11/13 23:44:18
27楼: 谢谢楼上,
不过去掉后,不能编译,红色的地方更多了。。。    :)


可能Demo里面的D7的东西还在..
----------------------------------------------
阳光总在
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
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);
----------------------------------------------
-
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
2021/11/14 10:56:53
29楼: 怎么设置Filter调用GDCL Mpeg-4能压缩输出MP4视频文件呢!!
----------------------------------------------
-
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
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);
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
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 之间的连接。没有问题的,再到自己的程序里面,用代码去连接。
----------------------------------------------
-
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
2021/11/16 8:26:04
32楼:  pcplayer,谢谢,我到今天才明白,这个FILTER不是随便组合的啊!研究中
----------------------------------------------
-
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
2021/11/16 13:35:54
33楼: 终于跑出来个WMV。声音也正常,不变音。谢谢pcplayer的大力帮助。
此帖子包含附件:
PNG 图像
大小:271.1K
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/17 18:07:34
34楼: 恭喜楼上。

这个 GraphEdit 就是图形化的连接 Filter 的工具。在这里测试成功后,你就可以在代码里面,用程序去连接这些 Filter 了。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/17 18:07:57
35楼: 关于声音正常:
正常的一个媒体文件,每一帧,都有时间戳;里面的声音数据,也有时间戳。在 DirectShow 里面,为了达到声画同步,视频数据的播放节奏,以声音数据的时间戳为准。这样能保证声音的播放连续。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/17 18:10:04
36楼: 至于你说才明白 Filter 不能随便组合,其实我前面的博客文章里面已经讲了啊。你前面是一个处理视频数据的 Filter 它输出视频数据,当然不能在后面接一个处理音频数据的 Filter,接上也没意义嘛。Filter 的 PIN 有个媒体类型的属性的,媒体类型不一致的,接不上去。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
2021/11/17 18:11:42
37楼: 写了一大段,还是有非法字符。还能不能好好讨论技术问题了
----------------------------------------------
-
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
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用过,不知道是什么效果了。

这两个都是可以在事件里取帧的,好像取的都是图元数据吧。
----------------------------------------------
-
作者:
男 pcplayer (pcplayer) ★☆☆☆☆ -
普通会员
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 工具就能看到。只要你电脑里面装过的,你就能使用,不需要有文档就能用。
----------------------------------------------
-
作者:
男 jljaaj (小强) ▲▲△△△ -
注册会员
2021/11/28 16:42:00
41楼: @ tiez  谢谢你的帮助。
----------------------------------------------
-
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v2.1 版权所有 页面执行54.6875毫秒 RSS