2023年3月

一、在控件中打开以下网址是可以播放其中的视频的,

https://www.runoob.com/try/try.php?filename=tryhtml5_video_js_prop

把网页代码改成自己的视频地址也是可以播放的,但放到自己控件中就播放不了了。百思不得其姐。

<!DOCTYPE html> 
<html> 
<head> 
<meta charset="utf-8"> 
<title>菜鸟教程(runoob.com)</title> 
</head>
<body> 

<div style="text-align:center"> 
  <button onclick="playPause()">播放/暂停</button> 
  <button onclick="makeBig()">放大</button>
  <button onclick="makeSmall()">缩小</button>
  <button onclick="makeNormal()">普通</button>
  <br> 
  <video id="video1" width="420">
    <source src="http://121.12.249.239:***/2020-07-02/02_65_6504_0_2842223200702164327.mp4" type="video/mp4">
    <source src="mov_bbb.ogg" type="video/ogg">您的浏览器不支持 HTML5 video 标签。</video>
</div> 

<script> 
var myVideo=document.getElementById("video1");functionplayPause()
{
if(myVideo.paused)
myVideo.play();
elsemyVideo.pause();
}
functionmakeBig()
{
myVideo.width
=560;
}
functionmakeSmall()
{
myVideo.width
=320;
}
functionmakeNormal()
{
myVideo.width
=420;
}
</script> </body> </html>

思考:没有启动缓存? 不能加载对应的js之类的静态文件过来?

着手点: 研究控件属性,输出控件浏览器 控制台的内容,看看是否有报错什么的,

二、在浏览器能打开的FLV视频网页,(一个视频流)

到控件中打不开视频,控件中 显示有点黑影

======================播放

用delphi 浏览器控件输出控制台信息

procedure
TForm4.chrm1ConsoleMessage(Sender: TObject;const browser: ICefBrowser; const message, source: ustring; line: Integer;outResult: Boolean);beginmmo1.Lines.Add(message+' '+source);end;

用这个地址 http://localhost:3333/test/multimedia#013800138999-2

信息展示如下:

用本地html时 file:///C:/Users/yc/Desktop/multimedia.html  信息展示如下:

用网页浏览器也播放不出来,大致错误如下:不允许加载本地视频; 播放时找不到资源

Not allowed to load local resource: blob:null/5059940d-d725-4ac1-8ab2-c6aef83f37f7  multimedia.html:1Uncaught (in promise) DOMException: The element has no supported sources.   flv-player.js:280value @ flv-player.js:280FLVPlayer.play @ multimedia.html:87playVideo @ multimedia.html:133onclick @ multimedia.html:136

百度一下:Not allowed to load local resource: blob:null 大致可以找到文章:

解决chrome报Not allowed to load local resource错误的方法 - 大园子 - 博客园
https://www.cnblogs.com/eoooxy/p/6085255.html

html5打开本地文件夹-开发者问答-阿里云开发者社区
https://developer.aliyun.com/devask/279003.html

适用window.URL.createObjectURL(Object obj)时出现的Not allowed to load local resource错误 - 程序园
http://www.voidcn.com/article/p-dmkfzehh-gr.html

===  两个思路:

调用远程网页,远程资源;(为啥控件中播放不出来?找出控件问题)

调用本地网页,远程资源;(怎么样才可以在浏览器加载回来远程资源并播放,解决Not allowed to load local resource: blob:null)

转: 流文件和媒体文件的不一样( flv和mp4,avi的区别) - - ITeye博客

https://www.iteye.com/blog/shencaifeixia-1202398

流文件和媒体文件的不一样( flv和mp4,avi的区别)

流文件媒体文件flvmp4avi
Q:为什么把flv叫做流式文件格式? 和mp4,avi不是一样都是音视频的容器吗? 有什么区别?
一下是我收集的几种解释,每个人有不同的理解,把这些都看一遍,你会理解的更加清晰

引用
通常说的流式文件是可以边传边解的,开始不需要整个文件。特点是有文件头信息(这个不是必需的)和中间打包了,可以直接解析分包,而且文件可以任意大小,而不需要通过索引分包。FLV,MPEG,RMVB等都可以直接依次分包解析,而MP4,AVI一定要依赖索引表才行,而且开始就要固定位置好,如果索引表在尾部,还没办法解析。

引用
流媒体文件是指多媒体文件边下载可以边观看的文件。而传统的视频文件需下载完成才能观看,而流媒体主要是下载一部分文件到缓存区,然后再从缓存区里面拿数据~而能作为这种流媒体文件的只有经过特殊编码的格式才适合,而flv、rmvb、mov、asf等格式文件才属于流媒体格式文件~


引用
对于HTTP协议,流式文件可以使用HTTP分段下载,由于在前面的先播放,所以可以一边下载一边播放,但是对于容器格式的文件,由于客户端不知道如何对文件解析(必须拿到整个文件才能解析),所以不能边下载边播放。
要实现对容器格式的文件的在线播放,必须要服务器支持流式播放接口,例如RTSP协议


引用
至于mpeg,avi,mpe这些也可以使用流化的方式来播放,但是效果不好,有网络传输的缺陷。


把控件放在  F:\DComp\windows_ocxdemo-new_Branches

解压文件后,一开始没有看到 delphi demo ,只看到文件夹中只有一个 .OCX文件没有看到dll 这些文件,表示诧异。管理员权限来到路径注册,提示如下:

百度一番,感觉不太对。后来递归了所有文件目录,查看所有文件。说明文档并不符合我。

看到F:\DComp\windows_ocxdemo-new_Branches\cab 路径下还有cmsv6.CAB 这个压缩包文件。解压后,注册 bat就在里面,顺利注册完成。

delphi导入 activeX控件后提示如下,yes


编译,安装控件

提示缺少 CMSV6OCXLib_TLB 把刚编译的控件 dcu文件拷贝进来

D:\360MoveData\Users\yc\Documents\RAD Studio\Projects\Win32\Debug\CMSV6OCXLib_TLB.dcu

删除完dcu文件夹下的  cx.. 和 dx..的dcu文件。

这个是压缩方面的,从自己项目中找来了两个 放到项目中导入进去。

改成PWideChar 即可

编译成功:

一台车有多个摄像头,一天时间每天摄像头有断续录像,要可视化显示出来,每个通道(摄像头)那个时间段有录像,鼠标点击能选中通道和对应的时间点并且可视化显示出来。

直观方便。 每选一台车就获取一次数据源,解释json一次。 生成对象,每次重绘就去根据对象数据画就好了。

本例子

typeTregion= class
  publicfR: TGPRect;
begintime, endtime: TDateTime;
//后面要改成整形 int end;
TChannel
= class publicregionList: TList<Tregion>;
name:
string;
order: Integer;
end;
TCar
= class private public //应该有 宽 高 车牌号,通讯号,和传过来的字符串 ChannelList: TList<TChannel>;
REGISTRATIONNO, Commno:
string;
fCarRect: Trect;
end;

出现的问题 在下方描述:

unituJsonTest;{有两个情形:
1、如果直接画在窗体的canvas中,窗体拖动屏幕外面再拖回来画面消失(不懂怎么解决)。
如果在FormPaint画会造成画面闪烁。OnResize中画正常。
2、如果画在一个放大的image的canvas中,窗体拖动屏幕外面再拖回来画面不会消失,
不需要在FormPaint中画。但 OnResize中画时却造成iamge右边有一片空白了(异常不知道如何解决)。

模式切换:在FormCreate(Sender: TObject);
mode := false; //切换情形 1true 2 false

打开窗体 点击绘制按钮
2020-10-13 09:14:04 情形2 的问题解决了。
} interface usesWinapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.Buttons, superobject,
Vcl.ExtCtrls, Vcl.Imaging.jpeg, uChannel, System.Generics.Collections,
Winapi.GDIPAPI, System.DateUtils, Winapi.GDIPOBJ;
typeTDrawForm= class(TForm)
mmo1: TMemo;
img1: TImage;
btnreadJson: TButton;
btndraw: TButton;
pnlLine: TPanel;
lbltime: TLabel;
tmr1: TTimer;
mmo2: TMemo;
procedurebtnreadJsonClick(Sender: TObject);procedureFormResize(Sender: TObject);procedurebtndrawClick(Sender: TObject);procedureFormCreate(Sender: TObject);procedureimg1Click(Sender: TObject);procedureimg1DblClick(Sender: TObject);procedureimg1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
procedureimg1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);proceduretmr1Timer(Sender: TObject);private //fTop,fbuttom,fLet,fRight:integer; drawWidth, rowCnt: Integer;
car: TCar;
fLeft: Integer;
mode, HaveReadJson: boolean;
SelectCommno:
string;
curDatetime: Tdatetime;
pt: TPoint;
StartTime, EndTime: cardinal;
OnlySingleClick: boolean;
public {Public declarations} end;constfTop= 105;
fbuttom
= 5;
fRight
= 8; //绘制区预保留右边空间 drawH = 25; //绘制每一行通道的高度 TimeLineH = 20; //刻度区高度包括文字 Part = 24; //24等分 Graduate = 7; //刻度高度 varDrawForm: TDrawForm;implementation {$R *.dfm} function Str2ToDatetime(DateStr: string): Tdatetime;//将yyyymmddhhnnss格式的字符串转为时间格式 varfs: TFormatSettings;beginInsert(':', DateStr, 13);
Insert(
':', DateStr, 11);
Insert(
' ', DateStr, 9);
Insert(
'-', DateStr, 7);
Insert(
'-', DateStr, 5);
fs.DateSeparator :
= '-';
fs.TimeSeparator :
= ':';
fs.ShortDateFormat :
= 'yyyy-mm-dd';
fs.ShortTimeFormat :
= 'hh:nn:ss';
Result :
= StrToDateTimeDef(DateStr, 0, fs);end;procedureTDrawForm.FormCreate(Sender: TObject);beginmode := false; //切换情形 1 true 2 false fLeft := 8;
lbltime.Left :
= -5;if not mode then beginimg1.Align :=alclient;end;
pnlLine.Width :
= 1;
pnlLine.Visible :
=false;

btnreadJson.Click;
end;procedureTDrawForm.btnreadJsonClick(Sender: TObject);varJsonstr: String;
ChannelList: TSuperArray;
ACArray: TSuperArray;
i, j: Integer;
jsonNode: ISuperObject;

channel: TChannel;
region: Tregion;
beginjsonNode :=SO(mmo1.Text);
ChannelList :
= jsonNode.A['ChannelList'];
car :
= TCar.Create;
car.REGISTRATIONNO :
= jsonNode.s['REGISTRATIONNO'];
car.Commno :
= jsonNode.s['Commno'];
car.ChannelList :
= TList<TChannel>.Create;

rowCnt :
=ChannelList.Length;
drawWidth :
= self.Width - fLeft -fRight;
drawWidth :
= drawWidth div Part *Part;
fLeft :
= (self.Width - drawWidth) div 2;
car.fCarRect.
Create(fLeft, fTop, fLeft + drawWidth, fTop + rowCnt *drawH);

pnlLine.Height :
= ChannelList.Length *drawH;
pnlLine.Left :
= -1;
pnlLine.Top :
=fTop;
lbltime.Top :
=fTop;
pnlLine.Visible :
=true;for i := 0 to ChannelList.Length - 1 do beginHaveReadJson := true; //放这里是为了要有通道 才... channel := TChannel.Create;
channel.name :
= '通道' + ChannelList.O[i].s['name'];
channel.order :
= ChannelList.O[i].i['order'];//channel.fRect:=nil; car.ChannelList.Add(channel);
channel.regionList :
= TList<Tregion>.Create();
ACArray :
= ChannelList.O[i].A['regionList'];for j := 0 to ACArray.Length - 1 do beginregion := Tregion.Create;
region.begintime :
= Str2ToDatetime(ACArray.O[j].s['begintime']);
region.EndTime :
= Str2ToDatetime(ACArray.O[j].s['endtime']);
channel.regionList.Add(region);
curDatetime :
= region.begintime; //sss end;end;

StartTime :
=GetTickCount;end;procedureTDrawForm.btndrawClick(Sender: TObject);vari, j: Integer;
Graphics: TGPGraphics;
opaquePen, semiTransPen: TGPPen;
rect: TGPRect;
region: Tregion;
fCanvas: Tcanvas;
Rect1: Trect;
begin if mode then beginself.Repaint;
fCanvas :
= self.Canvas; //情形1 end else beginfCanvas := img1.Canvas; //情形2 img1.Align :=alclient;//如果用图片绘制会有右边一片空白异常。感谢网友 [布吉]周黔76557298 帮忙 Rect1.Left := 0;
Rect1.Top :
= 0;
Rect1.Right :
=img1.Width;
Rect1.Bottom :
=img1.Height;with img1 do beginPicture.Graphic.Width :=Rect1.Right;
Picture.Graphic.Height :
=Rect1.Bottom;
Height :
=Rect1.Bottom;
Width :
=Rect1.Right;end;
fCanvas.FillRect(Rect1);
fCanvas.Brush.Color :
= clwhite; {设置画刷颜色, 也就是填充色}fCanvas.FillRect(Rect1);{填充窗体客户区} end;

img1.Width :
=self.Width;

rowCnt :
=car.ChannelList.Count;//showmessage(inttostr(rowCnt)); self.Height := fTop + fbuttom + TimeLineH + rowCnt *drawH;//showmessage(inttostr(Height)); //设定窗体高度 drawWidth := self.Width - fLeft -fRight;
drawWidth :
= drawWidth div Part *Part;
fLeft :
= (self.Width - drawWidth) div 2;
car.fCarRect.
Create(fLeft, fTop, fLeft + drawWidth, fTop + rowCnt *drawH);//窗体变化的时候需要计算 fCanvas.Font.Size := 8;
fCanvas.Font.Style :
=[];
fCanvas.Font.Color :
= $00464646; //clBlue fCanvas.Brush.Style :=bsClear;
fCanvas.Pen.Color :
=clSilver;
Graphics :
= TGPGraphics.Create(fCanvas.Handle); //Picture.Bitmap. opaquePen := TGPPen.Create(MakeColor(255, 153, 204, 255), drawH - 4);//设定一个笔 和颜色 和画笔的高度 for i := 0 to rowCnt - 1 do beginfCanvas.MoveTo(fLeft, fTop+ i *drawH);
fCanvas.LineTo(fLeft
+ drawWidth, fTop + i *drawH);for j := 0 to car.ChannelList[i].regionList.Count - 1 do beginregion :=car.ChannelList[i].regionList[j];
region.fR :
= Makerect(fLeft + trunc(SecondOfTheDay(region.begintime) *drawWidth/ 86400), fTop + i *drawH,
trunc(SecondsBetween(region.begintime, region.EndTime)
* drawWidth / 86400), drawH - 4);

rect :
=region.fR;

Graphics.DrawLine(opaquePen, rect.X, rect.Y
+ drawH div 2,
rect.X
+ rect.Width, rect.Y + drawH div 2); //其实就是画线, //fCanvas.MoveTo(rect.X, rect.Y+8); fCanvas.LineTo(rect.X+rect.Width, rect.Y+8); end;
fCanvas.TextOut(fLeft
+ drawWidth div 2, fTop + i * drawH + 4,
car.ChannelList[i].name);
end;
fCanvas.MoveTo(fLeft, fTop
+ rowCnt *drawH);
fCanvas.LineTo(fLeft
+ drawWidth, fTop + rowCnt *drawH);//添加刻度 fCanvas.Font.Color := $00464646; //clBlue clMaroon clSilver clblack for i := 0 to Part do beginfCanvas.MoveTo(fLeft+ drawWidth div Part * i, fTop + rowCnt *drawH);
fCanvas.LineTo(fLeft
+ drawWidth div Part * i, fTop + rowCnt * drawH +Graduate);if (i = 0) then beginfCanvas.TextOut(fLeft+ drawWidth div Part * i, fTop + rowCnt * drawH +Graduate, inttostr(i));end else if (i < 10) then beginfCanvas.TextOut(fLeft+ drawWidth div Part * i - 2,
fTop
+ rowCnt * drawH +Graduate, inttostr(i));end else if (i = 24) then beginfCanvas.TextOut(fLeft+ drawWidth div Part * i - 10,
fTop
+ rowCnt * drawH +Graduate, inttostr(i));end else beginfCanvas.TextOut(fLeft+ drawWidth div Part * i - 4,
fTop
+ rowCnt * drawH +Graduate, inttostr(i));end;end;end;procedureTDrawForm.FormResize(Sender: TObject);begin if (car <> nil) thenbtndraw.Click;end;procedureTDrawForm.img1Click(Sender: TObject);begin //如果在区域,获取xy坐标,移动panel 计算出时间,显示出来。 if HaveReadJson then begintmr1.Enabled :=true;//StartTime := GetTickCount; OnlySingleClick :=true;//mmo1.Lines.Add('单击 ' + inttostr(GetTickCount)); //StartTime := EndTime; //if (EndTime - StartTime) < 700 then //begin //StartTime := EndTime; //exit; //end //else //StartTime := EndTime; end;//mmo1.Lines.Add('*** '+datetimetostr(selectdatetime)); end;procedureTDrawForm.img1DblClick(Sender: TObject);begin //showmessage(datetimetostr(selectdatetime)); //TControl.ControlStyle //mmo1.Lines.Add('双击 '+inttostr(GetTickCount)); //EndTime := GetTickCount; //if (EndTime - StartTime) < 200 then //之前本来想用 计算时间差来判断。但不理想 //begin //OnlySingleClick := false; //end OnlySingleClick :=false;end;procedureTDrawForm.img1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
varchanelIndex, bb: Integer;
selectTime:
string;
cd: Double;
begin if HaveReadJson then beginpt.Create(X, Y);end;end;procedureTDrawForm.img1MouseMove(Sender: TObject; Shift: TShiftState;
X, Y: Integer);
varchanelIndex, bb: Integer;
selectTime:
string;
cd: Double;
begin if HaveReadJson then //如果鼠标移动跟着绘制线条会造成 识别不出 单击和双击。 可以试一下改成 定时器或线程执行 begin //pt.Create(X, Y); //// car.fCarRect //if car.fCarRect.Contains(pt) then // //begin //pnlLine.Left := X; // //chanelIndex:=(y-ftop)div drawH; //bb:=(X-fleft)*86400 div drawWidth; //cd:=bb/86400; //selectDatetime:= StartOfTheDay(curdatetime)+cd; //lbltime.Caption:=car.ChannelList[chanelIndex].name+' '+TimeToStr(selectDatetime); ////lbltime.Caption:=car.ChannelList[chanelIndex].name+' '+inttostr(bb); //if (X-fleft)>((20*drawWidth)div 24) then //lbltime.Left:= x-2-lbltime.Width //else //lbltime.Left:= x+2; //end; end;end;procedureTDrawForm.tmr1Timer(Sender: TObject);varchanelIndex, bb: Integer;
selectTime:
string;
cd: Double;
selectDatetime: Tdatetime;
//本次点击选择的时间 begintmr1.Enabled :=false;if car.fCarRect.Contains(pt) then // beginpnlLine.Left :=pt.X;
chanelIndex :
= (pt.Y - fTop) divdrawH;
bb :
= (pt.X - fLeft) * 86400 divdrawWidth;
cd :
= bb / 86400;
selectDatetime :
= StartOfTheDay(curDatetime) +cd;
lbltime.Caption :
= car.ChannelList[chanelIndex].name + ' ' +TimeToStr(selectDatetime);if (pt.X - fLeft) > ((20 * drawWidth) div 24) then //20刻度后把文字显示在竖线左边 lbltime.Left := pt.X - 2 -lbltime.Widthelselbltime.Left := pt.X + 2;if OnlySingleClick then //如果是单击 等一下 sleep(50);if not OnlySingleClick thenmmo1.Lines.Add('双击' +datetimetostr(selectDatetime))elsemmo1.Lines.Add('单击' +datetimetostr(selectDatetime));end;end;end.


objectDrawForm: TDrawForm
Left
= 335Top= 344Caption= #30011#22270#31383#20307ClientHeight= 294ClientWidth= 744Color=clWhite
DoubleBuffered
=True
Font.Charset
=DEFAULT_CHARSET
Font.Color
=clWindowText
Font.Height
= -11Font.Name= 'Tahoma'Font.Style=[]
OldCreateOrder
=False
Visible
=True
OnCreate
=FormCreate
OnResize
=FormResize
PixelsPerInch
= 96TextHeight= 13 objectimg1: TImage
Left
= 656Top= 8Width= 72Height= 67Align=alCustom
OnClick
=img1Click
OnDblClick
=img1DblClick
OnMouseDown
=img1MouseDown
OnMouseMove
=img1MouseMoveend objectlbltime: TLabel
Left
= 253Top= 170Width= 3Height= 13Color=clActiveCaption
ParentColor
=False
Transparent
=Falseend objectmmo1: TMemo
Left
= 81Top= 2Width= 392Height= 98ImeName= #20013#25991'('#31616#20307') -'#25628#29399#25340#38899#36755#20837#27861Lines.Strings=('{"REGISTRATIONNO":"'#31908 '88888","Commno":"18576628275","ChannelList":' '[{"name":"CH1","order":1,"regionList":' '[{"begintime":"20200927164456","endtime":"2020092717125' '6"},' '{"begintime":"20200927012256","endtime":"20200927026666666' '"}]},{"name":"CH2","order":2,"regionList":' '[{"begintime":"20200927164456","endtime":"2020092717666666' '6"},' '{"begintime":"20200927014456","endtime":"20200927026666666' '"}]},{"name":"CH3","order":3,"regionList":' '[{"begintime":"20200927164456","endtime":"2020092717666666' '6"},' '{"begintime":"20200927013356","endtime":"20200927022256' '"}]},{"name":"CH4","order":3,"regionList":' '[{"begintime":"20200927012556","endtime":"2020092701485' '6"},' '{"begintime":"20200927016666666","endtime":"20200927021256' '"},' '{"begintime":"20200927024456","endtime":"20200927026666666' '"},' '{"begintime":"20200927034456","endtime":"20200927036666666' '"},' '{"begintime":"20200927035856","endtime":"20200927042556' '"},' '{"begintime":"20200927045856","endtime":"20200927082556' '"},' '{"begintime":"20200927084856","endtime":"20200927182556' '"}]}]}')
TabOrder
= 0 end objectbtnreadJson: TButton
Left
= 0Top= 8Width= 75Height= 25Caption= #35299#37322'json'TabOrder= 1OnClick=btnreadJsonClickend objectbtndraw: TButton
Left
= 0Top= 39Width= 75Height= 25Caption= #32472#21046TabOrder= 2OnClick=btndrawClickend objectpnlLine: TPanel
Left
= 241Top= 170Width= 6Height= 137BevelOuter=bvNone
Color
=clBlue
ParentBackground
=False
TabOrder
= 3 end objectmmo2: TMemo
Left
= 479Top= 8Width= 130Height= 81ImeName= #20013#25991'('#31616#20307') -'#25628#29399#25340#38899#36755#20837#27861Lines.Strings=(
#
21487#20197#33258#24049#20462#25913#19968#27573'json'#27979#35797#65292#28857#20987#35299#37322'json')
TabOrder
= 4 end objecttmr1: TTimer
Enabled
=False
Interval
= 100OnTimer=tmr1Timer
Left
= 696Top= 80 end end

uJsonTest.dfm 窗体文件