1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ソラカメのLIVE映像をWebブラウザで再生するページをつくってみた

Last updated at Posted at 2025-03-12

概要

ソラカメで撮影した映像をブラウザで再生するページを作成してみた。
いろいろと注意して実装する必要があるので本記事にまとめる。

ソラカメとは

ブラウザでLIVE映像を再生させるためには

再生までにやらないといけないこと。

  1. SORACOM APIで認証情報を取得する
    SORACOM APIリファレンス-認証

  2. SORACOM APIを使用して視聴URLを取得する
    SORACOM APIリファレンス-視聴URL取得

  3. 視聴URLを動画プレイヤーに設定する

やってみた

以下、試行錯誤。

下準備

SAMユーザーの作成

SORACOM APIを実行するために下記を実施

  1. ソラコム管理画面からSAMユーザーを作成
    SAMユーザーの作成

  2. 作成したSAMユーザーの権限設定で「OAuth2:authorize」「SoraCam:getSoraCamDeviceStreamingVideo」を追加
    SAMユーザーの権限追加

{
  "statements": [
    {
      "api": [
        "SoraCam:getSoraCamDeviceStreamingVideo",
        "OAuth2:authorize"
      ],
      "effect": "allow"
    }
  ]
}

JavaScriptで実装してみた

まずはお手軽にJavaScriptで。

JavaScriptのコード

下記関数を作成。

// 認証情報を取得する
async function authenticate() {
  const url = 'https://api.soracom.io/v1/auth';

  try {
    const response = await axios.post(url, {
      authKeyId: 'secret-XXXX',
      authKey: 'keyId-XXXX'
    }, {
      headers: {
        'Content-Type': 'application/json'
      }
    });

    console.log("認証成功:", response.data);

    // 認証 API のレスポンスに適切なキーがあるか確認
    if (!response.data.apiKey || !response.data.token) {
      throw new Error("APIキーまたはトークンがレスポンスに含まれていません");
    }

    return response.data;

  } catch (error) {
    console.error("認証エラー:", error);
    return null; // 認証失敗時は null を返す
  }
}

// 視聴URLを取得する
async function getMpd(api_key, api_token) {
  const url = 'https://api.soracom.io/v1/sora_cam/devices/[device-id]/images/exports';

  try {
    const response = await axios.get(url, {
      headers: {
        'Content-Type': 'application/json',
        'X-Soracom-API-Key': api_key,
        'X-Soracom-Token': api_token
      }
    });

    console.log("MPD取得成功:", response.data);

    // MPD の URL を適切に取得する(レスポンス構造に合わせて変更)
    if (!response.data || !response.data.mpd_url) {
      throw new Error("MPD URLがレスポンスに含まれていません");
    }

    return response.data.mpd_url; // MPD URL を返す

  } catch (error) {
    console.error("MPD取得エラー:", error);
    return null; // エラー時は null を返す
  }
}

// 動画プレイヤーに視聴URLを設定する
async function setSrc() {
  let data = await authenticate(); // 認証を実行

  if (!data) {
    console.error("認証情報の取得に失敗しました");
    return;
  }

  let mpdUrl = await getMpd(data.apiKey, data.token);

  if (!mpdUrl) {
    console.error("MPDデータの取得に失敗しました");
    return;
  }

  const myPlayer = videojs("example-video");
  myPlayer.src({ type: 'application/dash+xml', src: mpdUrl });
  console.log("動画ソースを設定:", mpdUrl);
}

setSrc();

JavaScriptでの問題点

CORSのエラーとなってしまいSORACOM APIの実行ができない。

SORACOM APIの実行処理をAWSのAPI Gatewey+Lambdaへ移植

lambda(python)に移植したコード

import json
import os
import urllib.request

# 環境変数の取得
AUTH_KEY_ID = os.environ['authKeyId']
AUTH_KEY = os.environ['authKey']
DEVICE_ID = os.environ['device_id']

def lambda_handler(event, context):
    try:
        # 1. 認証してAPIキーとトークンを取得する
        auth_response = authenticate()
        api_key = auth_response['apiKey']
        api_token = auth_response['token']

        print("1:OK")

        # 2. 視聴URLを返却する
        export_url = get_mpd_url(api_key, api_token)

        print("2:OK")

        return {
            'statusCode': 200,
            'body': json.dumps({'url': export_url})
        }
    
    except Exception as e:
        return {
            'statusCode': 500,
            'body': json.dumps(f'Error: {str(e)}')
        }

# 認証を行い、APIキーとトークンを取得
def authenticate():
    url = 'https://api.soracom.io/v1/auth'
    headers = {
        'Content-Type': 'application/json'
    }
    data = json.dumps({
        'authKeyId': AUTH_KEY_ID,
        'authKey': AUTH_KEY
    }).encode('utf-8')

    req = urllib.request.Request(url, headers=headers, data=data, method='POST')
    with urllib.request.urlopen(req) as response:
        response_code = response.getcode()
        if response_code != 200:
            raise Exception(f'Authentication failed: {response_code}')
        return json.loads(response.read().decode('utf-8'))

# 視聴URLを返却する
def get_mpd_url(api_key, api_token):
    url = f'https://api.soracom.io/v1/sora_cam/devices/{DEVICE_ID}/stream'
    headers = {
        'Content-Type': 'application/json',
        'X-Soracom-API-Key': api_key,
        'X-Soracom-Token': api_token
    }

    req = urllib.request.Request(url, headers=headers, method='GET')
    with urllib.request.urlopen(req) as response:
        response_code = response.getcode()
        if response_code != 200:
            raise Exception(f'Image export request failed: {response_code}')
        export_response = json.loads(response.read().decode('utf-8'))
        print(export_response)
        return export_response["playList"][0]["url"]

※lambdaの環境変数にソラコムの管理画面から発行した認証キーID(authKeyId)、認証キーシークレット(authKey)を設定しておく
認証キー/認証キーシークレットの取得

※lambdaの環境変数にソラカメの管理画面より取得したデバイスID(device_id)を設定しておく
デバイスIDの取得

実装の参考記事-ソラカメで撮影した画像をwordpressで作成したwebサイトにスライドバーで時刻を選んで表示する!

API Gatewey(REST API) とLambdaを繋げる

別記事参照。
リンク準備中

作成したREST API
https://hoge.execute-api.ap-northeast-1.amazonaws.com/dev/stream

htmlページの用意

動画プレイヤーはvideo.jsを使用
video.jsとは

index.htmlとしてS3に配置

<!DOCTYPE html>
<html>
  <head>
    <title>LIVE TEST</title>
    <meta charset="UTF-8" />
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <link href="https://vjs.zencdn.net/8.16.1/video-js.css" rel="stylesheet" />
    <script src="https://vjs.zencdn.net/8.16.1/videojs-contrib-dash/videojs-dash.js"></script>
  </head>

  <body>
    <div>
      <video-js id=example-video width=640 height=360
                class="vjs-default-skin" controls>
      </video-js>
    </div>
    <script type="text/javascript" src="https://vjs.zencdn.net/8.16.1/video.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/videojs-contrib-dash/5.1.1/videojs-dash.min.js"></script>
    <script>
      async function getData() {
        try {
          const response = await fetch("https://hoge.execute-api.ap-northeast-1.amazonaws.com/dev/stream");

          if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
          }

          const data = await response.json();
          console.log(JSON.parse(data["body"]).url); // 取得したデータを表示
          return JSON.parse(data["body"]).url;
        } catch (error) {
          console.error("Error:", error);
        }
      }

      async function setupPlayer() {
        const myPlayer = videojs("example-video");

        try {
          const data = await getData(); // 非同期関数の結果を取得
          console.log(data);
          myPlayer.src({ type: 'application/dash+xml', src: data });
        } catch (error) {
          console.error("Failed to set video source:", error);
        }
      }

      setupPlayer();
    </script>
  </body>
</html>

まとめ

  • SAMの設定を忘れずに
  • JavaScriptだとSORACOM APIを呼び出すときにCORSエラーとなるため、APIを呼ぶ場合は中間サーバーの用意が必用
  • ソラカメの視聴URLはMPEG-Dashという配信方式なので一部環境で再生できないので注意
    windows Chrome : OK
    mac Safari : NG
    Android Chrome : OK
    iOS Sarari : NG
1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?