Node.jsでWebCamera画像をBlueSkyに投稿する方法

April 22, 2025 – 4:40 pm

Node.jsでWebCamera画像を投稿する方法をGoogle AI Studioに質問し、具体的なScriptを作成してもらった。作成したスクリプトをテストしてみるとみごとに一発で成功。

いろいろトライしてうまくいかなかったものを数秒で解決してくれた。驚き。なお、投稿先のBlueSkyアカウントは YamasNet@yamasnet.com

以下、質問内容、提示されたスクリプトと実行結果を記録しておいた。

質問内容:

webcameraの画像を直接投稿したいのですが、具体的なnodeのソースを教えてくれませんか?

スクリプト:
postWebcamImage.js:

// --- 設定 ---
require('dotenv').config();
const { BskyAgent } = require('@atproto/api');
const NodeWebcam = require('node-webcam');
const fs = require('fs'); 
// 投稿するテキスト
const postText = 'Webカメラからリアルタイム投稿テスト! 📸';
// 画像の代替テキスト (Alt Text)
const altText = 'Webカメラからキャプチャされた現在の風景';
// Webカメラのオプション (環境に合わせて調整)
const webcamOptions = {
  width: 1280,
  height: 720,
  quality: 90,
  delay: 0, // 秒単位の遅延
  saveShots: false, // Bufferとして直接取得するため false に
  output: "jpeg",   // 出力フォーマット (jpeg or png)
  device: false,    // falseでデフォルトデバイスを使用。特定のカメラを使う場合はデバイス名を指定 (例: "HD Pro Webcam C920")
  callbackReturn: "buffer", // "location" (ファイルパス), "buffer", "base64" から選択
  verbose: false    // ログ出力を抑制する場合は true
};
// BskyAgentの初期化
const agent = new BskyAgent({ service: BLUESKY_SERVICE });
  // --- Webカメラからのキャプチャ ---
  console.log('📷 Webカメラから画像をキャプチャ中...');
  let imageBuffer;
  try {
    // Webcamインスタンスを作成
    const Webcam = NodeWebcam.create(webcamOptions);

    // Promiseを使ってキャプチャ処理を待機
    imageBuffer = await new Promise((resolve, reject) => {
      Webcam.capture("temp_webcam_shot", (err, data) => { // 第一引数は必須だが、callbackReturnが'buffer'ならファイルは生成されないことが多い
        if (err) {
          console.error('❌ Webカメラからのキャプチャに失敗:', err);
          // node-webcamはエラー時にnullを返すことがあるため、明示的にエラーをrejectする
          return reject(new Error('Webカメラからのキャプチャに失敗しました。依存ツールがインストールされているか、カメラが接続されているか確認してください。'));
        }
        if (!data) {
           return reject(new Error('キャプチャデータが空です。'));
        }
        console.log('✅ 画像をBufferとして取得しました。');
        resolve(data); // Bufferデータを返す
      });
    });

    // Bufferが取得できたか最終確認
    if (!imageBuffer || !(imageBuffer instanceof Buffer)) {
        throw new Error('有効な画像Bufferを取得できませんでした。');
    }

  } catch (error) {
    console.error('❌ Webカメラ処理中にエラーが発生しました:', error.message);
    process.exit(1);
  }
// --- Blueskyへのログイン ---
  try {
    console.log('⏳ Blueskyにログイン中...');
    await agent.login({
      identifier: BLUESKY_HANDLE,
      password: BLUESKY_APP_PASSWORD,
    });
    console.log('✅ Blueskyにログインしました。');
  } catch (error) {
    console.error('❌ Blueskyへのログインに失敗しました:', error.message);
    process.exit(1);
  }
// --- Blueskyへの投稿 ---
  try {
    // 1. 画像のアップロード
    console.log('⏳ 画像をBlueskyにアップロード中...');
    const mimeType = `image/${webcamOptions.output}`; // オプションに基づいてMIMEタイプを設定
    const uploadResponse = await agent.uploadBlob(imageBuffer, {
      encoding: mimeType,
    });
    console.log('✅ 画像をアップロードしました:', uploadResponse.data.blob.cid); // CIDなどを確認

    // 2. 投稿の作成
    console.log('⏳ 投稿を作成中...');
    const postRecord = {
      $type: 'app.bsky.feed.post',
      text: postText,
      createdAt: new Date().toISOString(),
      embed: {
        $type: 'app.bsky.embed.images',
        images: [
          {
            image: uploadResponse.data.blob, // アップロードされたBlobの参照
            alt: altText,
          },
        ],
      },
      // langs: ['ja'], // 必要なら言語を指定
    };

スクリプトの実行と結果

captureAndPost();

🚀 スクリプトを開始します...
📷 Webカメラから画像をキャプチャ中...
Promise {  }
✅ 画像をBufferとして取得しました。
⏳ Blueskyにログイン中...
✅ Blueskyにログインしました。
⏳ 画像をBlueskyにアップロード中...
✅ 画像をアップロードしました: undefined
⏳ 投稿を作成中...
🎉 投稿に成功しました!
🔗 Post URI: at://did:plc:7qpfwd2uadrefzw2oueisrzn/app.bsky.feed.post/3lnf3h2tr2g2s

Post a Comment