TEdgeBrowser(WebView2)でブラウザのWebCam(カメラ)映像を取得する機能をDelphiから使用してカメラ映像を表示する
Delphi 11.3(Community Edition)でTEdgeBrowserを使ってブラウザのWebCam(カメラ)映像を取得する機能を使用します。
パソコンにカメラ(WebCam)が機能が搭載されているかUSBカメラを接続して使用してください。
(1)はじめに
Windows10の場合はMicrosoft WebView2 ランタイムのインストールを以下のURLを参照してインストールしてください。
https://mam-mam.net/delphi/tedgebrowser.html
「WebView2Loader.dll」も、
https://mam-mam.net/delphi/tedgebrowser.html
を参照してください。
また、以下URLにある「WebView2_TLB.pas」を、本プロジェクトのフォルダに配置してください、
https://mam-mam.net/delphi/tedgebrowser_webview2.html
(2)プロジェクトの作成と保存
Delphi IDEを起動し、「ファイル」⇒「Windows VCLアプリケーション -Delphi」をクリックします「ファイル」⇒「すべて保存 Ctrl+Shift+S」をクリックして、プロジェクト保存用フォルダを作成して ユニット(Unit1)とプロジェクト(Project1)を保存します
上述のように「WebView2_TLB.pas」をプロジェクトフォルダ内に配置してください。
次に、「プロジェクト」⇒「Project1をビルト Shift+F9」をクリックして事前に一度コンパイルしておきます。(フォルダが生成される)
プロジェクトフォルダ内の「win32\degub」フォルダに「files」フォルダを作成します。
「win32\degub\files」フォルダ内に、以下のHTMLファイル「index.html」を作成してUTF-8で保存してください。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> </head> <body> <script> let video,prev,prev_ctx,w,h,strm=null,isStart=false; window.addEventListener('load',function(event){ video=document.createElement('video'); video.setAttribute("autoplay",""); video.setAttribute("muted",""); video.setAttribute("playsinline",""); video.onloadedmetadata = function(e){video.play();}; prev=document.createElement("canvas"); prev_ctx=prev.getContext("2d", {willReadFrequently:true}); console.log("event:loaded"); }); function start(){ isStart=true; //カメラ使用の許可ダイアログが表示される navigator.mediaDevices.getUserMedia( //マイクはオフ, カメラの映像は前面カメラで640×480を希望する //背面カメラを希望する場合は "facingMode":"environment" //前面カメラを希望する場合は "facingMode":"user" {"audio":false,"video":{"facingMode":"user","width":640,"height":480}} ).then( //許可された場合 function(stream){ video.srcObject = stream; strm=stream; //0.5秒後にスキャンする setTimeout(Scan,500,true); } ).catch( //許可されなかった場合(Permission denied) function(err){ console.log("error:"+err.message);//■エラー } ); } function stop(){ isStart=false; if(strm!==null){ strm.getTracks().forEach(track => track.stop()); strm=null; } } function Scan(first){ if(first){ //選択された幅高さ w=video.videoWidth; h=video.videoHeight; //内部のサイズ prev.setAttribute("width",w); prev.setAttribute("height",h); } if(isStart){ prev_ctx.drawImage(video,0,0,w,h); let src=prev.toDataURL("image/png"); console.log("image:"+src); if(isStart){ setTimeout(Scan,100,false); } } } </script> </body> </html>
(3)フォームの設計
フォームに、TEdgeBrowser×1個、TButton×2個と、TMemo1×1個、TImage×1個をドラッグ&ドロップします

(4)ソースコードの記述
フォームのButton1をダブルクリックしてソースコードを記述します。
unit Unit1; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Winapi.WebView2, Winapi.ActiveX, Vcl.StdCtrls, Vcl.Edge, WebView2_TLB, Vcl.ExtCtrls, Vcl.Imaging.pngimage; type TForm1 = class(TForm) EdgeBrowser1: TEdgeBrowser; Button1: TButton; Button2: TButton; Memo1: TMemo; Image1: TImage; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure EdgeBrowser1DevToolsProtocolEventReceived( Sender: TCustomEdgeBrowser; const CDPEventName, AParameterObjectAsJson: string); private { Private 宣言 } png:TPngImage; strm:TMemoryStream; public { Public 宣言 } end; //クラスヘルパーでプロパティFWebViewを読めるようにする TMyCustomEdgeBrowser = class helper for TCustomEdgeBrowser function GetCoreWebView():ICoreWebView2_3; end; var Form1: TForm1; implementation {$R *.dfm} uses System.NetEncoding, System.JSON.Serializers, System.IOUtils; { TMyCustomEdgeBrowser } //クラスヘルパーでプロパティFWebViewを読めるようにする function TMyCustomEdgeBrowser.GetCoreWebView: ICoreWebView2_3; begin with self do result:=WebView2_TLB.ICoreWebView2_3(FWebView); end; { TForm1 } procedure TForm1.Button1Click(Sender: TObject); begin Button1.Enabled:=False; Button2.Enabled:=True; //Javascriptのカメラ映像取得の開始 EdgeBrowser1.ExecuteScript('start()'); Memo1.Lines.Add('開始'); end; procedure TForm1.Button2Click(Sender: TObject); begin Button1.Enabled:=True; Button2.Enabled:=False; //Javascriptの位置情報取得を開始する EdgeBrowser1.ExecuteScript('stop()'); Memo1.Lines.Add('停止'); end; procedure TForm1.EdgeBrowser1DevToolsProtocolEventReceived( Sender: TCustomEdgeBrowser; const CDPEventName, AParameterObjectAsJson: string); type TJsonMsg=record column:Integer; level:String; line:Integer; source:String; text:String; url:String; end; TJsonMessage=record message:TJsonMsg; end; var s:TJsonSerializer; res:TJsonMessage; b:TBytes; begin s:=TJsonSerializer.Create; try res:=s.Deserialize<TJsonMessage>(AParameterObjectAsJson); if res.message.text='event:loaded' then begin Button1.Enabled:=True; end else if pos('error:',res.message.text,1)=1 then begin Memo1.Lines.Add('エラー:'+res.message.text.Substring(6)); Button1.Enabled:=True; end else if pos('image:',res.message.text,1)=1 then begin b:=TNetEncoding.Base64.DecodeStringToBytes(res.message.text.Substring(28)); strm.Size:=0; strm.Write(b,length(b)); strm.Position:=0; png.LoadFromStream(strm); //画面のちらつきを抑える処理 LockWindowUpdate(Self.Handle); Image1.Picture.Bitmap.Assign(png); LockWindowUpdate(0); //画面のちらつきを抑える処理の解除 end; finally s.Free; end; end; procedure TForm1.FormCreate(Sender: TObject); var wb:ICoreWebView2_3; cachepath:string; begin Button1.Enabled:=False; Button2.Enabled:=False; Button1.Caption:='カメラ映像取得'; Button2.Caption:='停止'; Image1.Proportional:=True; Image1.Stretch:=True; Memo1.Lines.Clear; strm:=TMemoryStream.Create; png:=TPngImage.Create; cachepath:=ExtractFilePath(Application.ExeName)+'cache'; //キャッシュを削除する if DirectoryExists(cachepath) then TDirectory.Delete(cachepath,true); //キャッシュのフォルダを指定する //ここに作成される「EBWebView」フォルダを削除すればキャッシュを消せる EdgeBrowser1.UserDataFolder:=cachepath; if not EdgeBrowser1.WebViewCreated then begin EdgeBrowser1.CreateWebView; while not EdgeBrowser1.WebViewCreated do begin sleep(100); application.ProcessMessages; end; end; //コンソールの使用を申請する EdgeBrowser1.DefaultInterface.CallDevToolsProtocolMethod( 'Console.enable', '{}', nil); //コンソールにメッセージが出力された時に //[DevToolsProtocolEventReceived]イベンを発生させる EdgeBrowser1.SubscribeToCDPEvent('Console.messageAdded'); //WebView2の取得 wb:=EdgeBrowser1.GetCoreWebView; // https://demo/ を .\filesフォルダに割り当てます wb.SetVirtualHostNameToFolderMapping( 'demo', PWideChar(ExtractFilePath(Application.ExeName)+'files'), COREWEBVIEW2_HOST_RESOURCE_ACCESS_KIND_ALLOW ); //ローカルファイル \files\index.htmlを読みます EdgeBrowser1.Navigate('https://demo/index.html'); end; procedure TForm1.FormDestroy(Sender: TObject); begin strm.Free; png.Free; end; end.
(5)「WebView2Loader.dll」ファイルを実行ファイルと同じフォルダ内にコピーする
「C:\Program Files (x86)\Embarcadero\Studio\22.0\Redist\win32\WebView2Loader.dll」
ファイルを、実行ファイルと同じフォルダ内(プロジェクト保存フォルダ\Win32\Debug)にコピーします
(A)「Debug」ビルトで 「Windows 32ビット」 |
プロジェクト保存フォルダ\Win32\Debug |
(B)「Debug」ビルトで 「Windows 64ビット」 |
プロジェクト保存フォルダ\Win64\Debug |
(C)「Release」ビルトで 「Windows 32ビット」 |
プロジェクト保存フォルダ\Win32\Release |
(D)「Release」ビルトで 「Windows 64ビット」 |
プロジェクト保存フォルダ\Win64\Release |
(6)実行する
「実行」⇒「実行」をクリックすると実行します。
しばらく待つと「カメラ映像取得(Button1)」ボタンが有効になります。

「カメラ映像取得(Button1)」ボタンをクリックします
カメラの使用を求めるダイアログが表示された場合は「許可」をクリックしてください。
成功した場合はカメラからの画像がImage1に表示されます。

