import video from local PC

Electron

preload.js

const { contextBridge, ipcRenderer } = require("electron");

contextBridge.exposeInMainWorld("electronAPI", {
  openVideo: () => ipcRenderer.invoke("dialog:openVideo"),
});

main.js

const { app, BrowserWindow, dialog, ipcMain } = require("electron");
const path = require("path");
// node.jsのfs(FileSystem)モジュールであり、ローカルPCのファイルを読み込む(書き込む)ときに必要
const fs = requrie("fs");

functino createWindow() {
  const win = new BrowserWindow({
    width: 1000,
    height; 1200,
    webPreferences: {
      preload: path.join(__dirname, "preload.js"),
      nodeIntegration: false,
      contextIsolation: true,
    },
  });
  win.loadURL("http://localhost:5173");
}

app.whenReady().then(createWindow);

ipcMain.handle("dialog:openVideo", async () => {
  // ※1
  const result = await dialog.showOpenDialog({
    // 単一ファイルを選択する設定
    properties: ["openFile"],
    // 選択できるファイル形式を制限する
    filters: [{ name: "Videos", extensions: ["mp4", "webm", "ogg"] }],
  });
  // ユーザーがキャンセルした場合や選んだファイルがない場合はnullを返して終了
  if (result.canceled || result.filePaths.length === 0) return null;

  // 単一ファイルしか選択できないのでfilePaths[0]でOK
  const filePath = result.filePaths[0];
  // fs.readFileSync で読み込んだファイルはバイナリデータです
  const data = fs.readFileSync(filePath);
  // 読み込んだバイナリデータをBase64文字列に変換します
  // Viteの開発サーバーではローカルファイルを直接指定すると、(<video src="file:///C:/...">)
  // ブラウザのセキュリティ制限で読み込めません
  // Base64にすると、ローカルファイルのパスを使わなくても<video>タグで再生できるようになります
  const base64 = data.toString("base64");
  // data:video/mp4;base64,AAA... のような形をData URIと呼びます
  // ブラウザがBase64文字列を動画や画像として認識して再生する際はこのような形にしてsrc={}にセットします
  return `data:video/mp4;base64,${base64}`;
});


-----
※1 ... result は以下の構造のオブジェクトとして返ってきます
{
  canceled: false,  <-- ユーザーがキャンセルしたか
  filePaths: ["C:/path/to/video.mp4"]
}

src/pages/Home.jsx

import React from 'react';
import { useState } from 'react';

export default functino Home() {
  const [videoSrc, setVideoSrc] = useState(null);

  const handleSelectFile = async () => {
    const filePath = await window.electronAPI.openVideo();
    if (filePath) setVideoSrc(filePath);
  };

  return (
    <>
      <button onClick={hanleSelectFile}>動画を選択</button>
      {videoSrc && (
        <video src={videoSrc} controls />
      )}
    </>
  );
}
BACK