ローカルのMP4ファイルの１フレームを画像保存するツール

## 0.はじめに

こんな感じです。

* 私は非エンジニアのドシロウトです
* 私はChromeOS Flexの愛用者です
* ChromeOS FlexはLinux開発環境もありますが、基本的にブラウザーのChromeメインのOSです
* 私はYoutubeとかでサムネ画像を作るときにアップした動画の1フレームをそのまま、または、加工して使います
* ブラウザーでMP4から指定の再生位置のフレームを切り出し、ローカルに保存するツールが欲しかった
* 適当なツールがなかったので作った
* 生成AI [perplexity](https://www.perplexity.ai/) 先生に聞きながらつくった

## 1.作ったもの

動画はこんな感じ

https://twitter.com/basictomonokai/status/1784369944404369736

## 2.プレイグラウンド

[Codepen](https://codepen.io/sf-os/pen/mdggJOm) に貼りました

<p class="codepen" data-height="600" data-default-tab="result" data-slug-hash="mdggJOm" data-user="sf-os" style="height: 600px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/sf-os/pen/mdggJOm">
  MP4から適当な再生位置選んでキャプチャー</a> by sf-os (<a href="https://codepen.io/sf-os">@sf-os</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

## 3.コード

HTMLファイル一枚です。(Codepenのまんま)


```HTML:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>MP4キャプチャー</title>
    <style>
    #my-canvas {
      display: none;
    }
    #inparea,#caparea {
      margin-bottom: 5px;
    }
    input,button,label {
      font-size: 1.2rem;
      color: #1317a0;
    }

    </style>
</head>
<body>
    <div id="inparea">
      <label for="file-input">
        MP4を読込
        <input id="file-input" type="file" accept="video/mp4">
      </label>
      
    </div>
    <div id="videoarea"><video controls id="my-video" src="" width="800px"></video></div>
    <div id="caparea"><button onclick="captureFrame()">MP4をキャプチャー</button></div>
    <div id="canarea"><canvas id="my-canvas"></canvas></div>
    <div id="imgarea"><img id="my-img" width="800px" src="https://placehold.jp/3d4070/ffffff/800x450.jpg?text=%E7%94%BB%E5%83%8F%E8%A1%A8%E7%A4%BA%E3%82%A8%E3%83%AA%E3%82%A2"></div>
    <div id="downarea"><button id="download-btn">キャプチャー画像ダウンロード</button></div>    
    <script>
    function captureFrame() {
      const video = document.getElementById('my-video');
      const canvas = document.getElementById('my-canvas');
    
      // canvasのサイズを動画のサイズに合わせる
      canvas.width = video.videoWidth;
      canvas.height = video.videoHeight;
    
      // canvasに動画の静止画を描画
      const ctx = canvas.getContext('2d');
      ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
      setTimeout(imggen,1000)
    }

    function imggen() {
      // canvasタグの参照を取得
      const canvas = document.getElementById('my-canvas');
      const img = document.getElementById('my-img');

      // canvasの内容をjpegに変換
      const dataURL = canvas.toDataURL('image/jpeg', 0.9); // 0.9は画質を表す

      // 変換したデータURLを設定
      img.src = dataURL;
    }

    // ファイル入力要素からファイルを取得
    const fileInput = document.getElementById('file-input');
    fileInput.addEventListener('change', handleFileChange);

    function handleFileChange(event) {
      const file = event.target.files[0];

      // ファイルをblobに変換
      const blob = new Blob([file], { type: 'video/mp4' });

      // blobをvideo要素のソースにセット
      const videoElement = document.getElementById('my-video');
      videoElement.src = URL.createObjectURL(blob);
      this.value = '';
    }

    const downloadBtn = document.getElementById('download-btn');
    const imageElement = document.getElementById('my-img');

    downloadBtn.addEventListener('click', () => {
      // imgタグのsrcからファイル名を取得
      const fileName = 'mp4thumb.jpg';

      // ダウンロード用のリンクを作成
      const downloadLink = document.createElement('a');
      downloadLink.href = imageElement.src;
      downloadLink.download = fileName;
      downloadLink.click();

      // ダウンロード用リンクを削除
      downloadLink.remove();
    });

    </script>
    
    
</body>
</html>
```

## 4.終わりに

欲しいツールをネットで探しまくるより、[perplexity](https://www.perplexity.ai/) 先生にスニペットを教えてもらって組み合わせるほうが楽かもしれない。

１０回位、部分的なスニペットを質問して組み合わればできる感じだった。

生成AIすごいｗ

以　上