17
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

ラズパイでYouTube APIを使ってライブ配信を行う

Last updated at Posted at 2023-03-07

概要

ラズパイからYouTube Liveを利用してライブ配信をします

ライブのたびに YouTube Studio の操作が必要になる紹介記事が多いのですが
本記事では YouTube Live Streaming API を利用して、ライブの準備、配信、アーカイブをおこないます

前半は YouTube API (= Google API) を利用できるようになるまで
具体的には Google Cloud Consoleプロジェクト を作成するところから
APIへのアクセスに必要な ACCESS TOKEN を入手するところまで

後半は YouTube Live Streaming API を利用して
ライブの準備、配信、アーカイブを行う手順

を紹介します。

補足的に必要な知識として

  • ffmpegによるストリーミング
  • YouTube Live Streaming API における Broadcasts と Streams の概念とライフサイクル

の話も紹介します

目次

前半 : YouTube API を利用できるように準備する

前半はラズパイもコーディングも不要です
太字はこれから作るものの固有名詞です
とりあえず「あー、そういうものを作るのね」と思っておいてください
APIにアクセスするためのゴールは ACCESS TOKEN なのですが、REFRESH TOKEN さえあれば何度でも生成できます

  1. [前半-1] プロジェクトを作成する
  2. [前半-2] YouTube Data APIを有効にする
  3. [前半-3] 認証情報を作成する
  4. [前半-4] OAuth同意画面を作成する
  5. [前半-5] OAuthを実行して code を入手する
  6. [前半-6] REFRESH TOKENを入手する
  7. [前半-7] ACCESS TOKENを入手する

後半 : YouTube Live Streaming API を利用してライブ配信する

  1. [後半-1] まず YouTube Studio を使ってラズパイからライブ配信をしてみる (ffmpegによるストリーミング)
  2. [後半-2] (座学) YouTube Live Streaming API における BroadcastsStreams の概念とライフサイクル (飛ばしてもよい)
  3. [後半-3] YouTube Live Streaming APIでライブ配信をする① (準備)
  4. [後半-4] YouTube Live Streaming APIでライブ配信をする② (配信)
  5. [後半-5] YouTube Live Streaming APIでライブ配信をする② (終了、アーカイブ)

目次を見るだけでも「うへ~、ながっ」と思うかもしれませんが
一つ一つ進めていけば大丈夫です
途中で REFRESH_TOKEN が手に入るのですが、
そうすれば Google Cloud Console での煩雑な作業も不要になるので頑張りましょう

手順

前半

1. [前半-1] プロジェクトを作成する

ブラウザで Google Cloud Console を開きます
自分のアカウントでログインしている状態になると思いますが、
そうでない場合は Googleアカウントを作成して、ログインしてください。

左上のプロジェクト名(自分の例ではSidecar)が表示されているドロップダウンをクリックします
image.png
プロジェクトの選択ダイアログが表示されるので、右上の「新しいプロジェクト」をクリックします
image.png
プロジェクト名を適当につけて「作成」
image.png
しばらく待つと「プロジェクト XXXXX を作成」という通知がきます
image.png

2. [前半-2] YouTube Data APIを有効にする

通知の「プロジェクトを選択」をクリックします
image.png
プロジェクトが選択された状態になるので、左側のペインから「APIとサービス」>「有効なAPIとサービス」をクリックします
image.png
「+APIとサービスの有効化」をクリックします
image.png
「YouTube Data API v3」を選択します。Streaming APIもこの中に入っています
image.png
「有効にする」をクリックします
image.png
API/サービスの詳細の画面に戻って、画面右上に「認証情報を作成する」と出るので、それをクリックします
image.png
※ なお、最後のステップで「認証情報を作成する」を押さずに画面を変えてしまった場合でも、
※ 同じ情報は、左のペインの「認証情報」「OAuth同意画面」から入力できます
※ 画面遷移などは多少違いますが、大丈夫です

3. [前半-3] 認証情報を作成する

まえの手順で「認証情報を作成する」を押すと「認証情報の作成」ウィザードが立ち上がります。

① 認証情報の種類 ではユーザデータを選択します。「次へ」で次のステップへ
image.png
② OAuth同意画面では、適当にアプリ名をつけます
ユーザーサポートメール、メールアドレスには自分のgmailのメールアドレスを入れておきます
※ 届くメールアドレスならば何でも大丈夫です
image.png
③ スコープでは「スコープを追加または削除」をクリックします
image.png
すると「選択したスコープの更新」ダイアログが表示されます
フィルタに YouTube と入力すると補完されるので YouTube Data API v3 を選択
下のリストから

  • .../auth/youtube
  • .../auth/youtube.force-ssl
  • .../auth/youtube.upload

を選択します
image.png
④ OAuthクライアントIDではアプリケーションの種類で「デスクトップアプリ」を選び、名前は適当につけます
「作成」をクリックすると、認証情報が作成されます
すこしだけ時間がかかります
image.png
⑤ 認証情報画面では作成された認証情報が確認できます
「ダウンロード」を押すとjsonファイルが取得できるので、適当な場所に保存しておきます
jsonファイルの中の client_idclient_secret が後々必要な情報となります
また redirect_urishttp://localhost になっていると思います
一応覚えておきましょう
image.png
ダウンロードされたjsonにはこんな情報が含まれています。ご参考まで

{
    "installed":{
        "client_id":"xxxxx.apps.googleusercontent.com",
        "project_id":"test-project-for-qiita",
        "auth_uri":"https://accounts.google.com/o/oauth2/auth",
        "token_uri":"https://oauth2.googleapis.com/token",
        "auth_provider_x509_cert_url":"https://www.googleapis.com/oauth2/v1/certs",
        "client_secret":"xxxxx",
        "redirect_uris":["http://localhost"]
    }
}

4. [前半-4] OAuth同意画面を作成する

左のペインの「OAuth同意画面」をクリックし「アプリを編集」をクリックします
image.png
いくつかステップがありますが、「保存して次へ」を押して ③テストユーザー まで行きます
image.png
image.png
「+ ADD USERS」をクリックします
image.png
「ユーザを追加」ダイアログで自分のgmailのメールアドレスを追加しておきます
image.png
「保存して次へ」をクリックします
image.png
最後に確認画面が表示されるので「ダッシュボードに戻る」をクリックします
image.png

これで、OAuthを実行して code を入手する準備が整いました
Google Cloud Consoleを利用するのはここまでになります

次の手順以降、各種KEYやIDをコピーペーストで入力していきますので、
もしテキストファイルなどにコピペしていない場合は、コンソールは開きっぱなしがいいと思います

5. [前半-5] OAuthを実行して code を入手する

ブラウザでOAuthを実行します
OAuth完了時にリダイレクトされたURLの一部に code が記載されているのでそれを回収します

まずURLを作ります
書式は

https://accounts.google.com/o/oauth2/v2/auth? \
    scope={ スコープ }&
    access_type=offline&
    include_granted_scope=true&
    response_tuype=code&
    redirect_url={ リダイレクト先のURL }&
    client_id={ Client ID }

です
スコープもリダイレクト先のURLも Google Cloud Console で設定した値を使うので
URLは以下になります

https://accounts.google.com/o/oauth2/v2/auth?scope=https://www.googleapis.com/auth/youtube%20https://www.googleapis.com/auth/youtube.force-ssl&access_type=offline&include_granted_scope=true&response_type=code&redirect_uri=http://localhost&client_id={ Client ID を入力 } となります

上記URLをブラウザで開くと、OAuthが始まります
まずはアカウントの選択
自分のアドレス(xxxx@gmail.com)をクリックします
image.png
「続行」をクリック
image.png
二つのチェックボックスの両方にチェックを入れて「続行」をクリック
image.png
リダイレクトURLで指定したアドレスを開こうとして Not Found になります
これは 期待動作(想定通り) なのでご安心ください
ブラウザに表示されているURLをコピペしてテキストエディタなどにはりつけます
code=&scope= の間の文字列が code になります
image.png
※ ちょうど黄緑色で塗りつぶしたところに code が入っています

6. [前半-6] REFRESH TOKENを入手する

ここからは curl コマンドを利用して、Google APIにアクセスします

Client ID
Client Secret
code
の3つの情報を利用して、以下のように curl コマンドを実行します

$ curl -d client_id={ Client ID を入力 } -d client_secret={ Client Secret を入力 } -d redirect_uri=http://localhost -d grant_type=authorization_code -d code={ codeを入力 } https://accounts.google.com/o/oauth2/token

googleからjsonが返ってきます
このjsonのなかに refresh_token が含まれています
絶対なくさないようにメモして保存しておきましょう
これからずっと使います
image.png

pi@raspberrypi:~ $ curl -d client_id=XXXXX.apps.googleusercontent.com -d client_secret=XXXXX -d redirect_uri=http://localhost -d grant_type=authorization_code -d code=XXXXX https://accounts.google.com/o/oauth2/token
{
  "access_token": "XXXXX",
  "expires_in": 3599,
  "refresh_token": "XXXXX",
  "scope": "https://www.googleapis.com/auth/youtube.force-ssl https://www.googleapis.com/auth/youtube",
  "token_type": "Bearer"
}

じつはお気づきのかたもいるかとは思いますが、
このjsonには access_token も含まれています
もちろん使えます
ただ、次の行に "expres_in": 3599 とあるように、約1時間で有効期限が切れて使えなくなります
その時には次の手順で再度新しい access_token を発行します

7. [前半-7] ACCESS TOKENを入手する

Client ID
Client Secret
REFRESH TOKEN
の3つの情報を利用して、以下のように curl コマンドを実行します

curl -d refresh_token={ REFRESH_TOKEN を入力 } -d client_id={ Client ID を入力 } -d client_secret={ 
 Client Secret を入力 } -d grant_type=refresh_token https://www.googleapis.com/oauth2/v4/token

googleからjsonが返ってきます
このjsonのなかに access_token が含まれています
image.png

pi@raspberrypi:~ $ curl -d client_id=XXXXX.apps.googleusercontent.com -d client_secret=XXXXX -d grant_type=refresh_token https://www.googleapis.com/oauth2/v4/token
{
  "access_token": "XXXXX",
  "expires_in": 3599,
  "scope": "https://www.googleapis.com/auth/youtube.force-ssl https://www.googleapis.com/auth/youtube",
  "token_type": "Bearer"
}

refresh_token から取得した access_token も約1時間の有効期限付きです
Expireしたら再度同じ操作で access_token を取得してください

ここまでで前半の終了です
お疲れさまでした

後半

1. [後半-1] まず YouTube Studio を使ってラズパイからライブ配信をしてみる (ffmpegによるストリーミング)

まずは YouTube Studio でライブ配信イベントを手動で作成して
ラズパイからライブ配信を行ってみます
YouTube側がライブ配信を受け入れられるときに、ラズパイ側がきちんと送出できるかの確認です

まずブラウザで
YouTube のサイトに行き
画面右上の自分のアイコンをクリックします
image.png
表示されるドロップダウンから YouTube Studio をクリックします
image.png
YouTube Studio の画面の右上の「作成」をクリックし
表示されたドロップダウンの「ライブ配信を開始」をクリックします
image.png
ライブ配信画面で ストリームキーストリームURL をコピーします
(右のコピーボタンを押してテキストエディタなどに張り付けておきましょう)
image.png

ここからはラズパイでの操作になります

ffmpegをインストールします

$ sudo apt-get install ffmpeg

YouTubeへの配信の際
音が必ず必要になります
今回マイクデバイスを用意しなかったので、無音MP3を代わりに流すことにします
(お気に入りのMP3があればそれを使っても構いません。ただし著作権にはご注意を...)

no_sound-1.mp3 ※右クリックして「名前を付けて保存」してください
クリキのキロク様に感謝

ラズパイのコマンドラインからダウンロードしたい場合は curl でダウンロードしましょう

$ curl https://log.mkuriki.com/wp-content/uploads/2022/01/no_sound-1.mp3 --output no_sound-1.mp3

次にラズパイに接続されているカメラデバイスを検索します
$ v4l2-ctl コマンドを利用します
mmal service 16.1 (platform:bcm2835-v4l2-0) がラズパイカメラです
今回はこれを使います。よってデバイス名は /dev/video0 です

余談ですが、一番下の UVC Camera (534d:2109): USV Vid (usb-3f980000.usb-1.5):
ラズパイに取り付けた HDMI-USB キャプチャです
このようにUVCデバイスを認識してくれるので、WebカメラやHDMI出力できるカメラから
ストリーミングするのも簡単です (すごいなラズパイ)

pi@raspberrypi:~ $ v4l2-ctl --list-devices
bcm2835-codec-decode (platform:bcm2835-codec):
        /dev/video10
        /dev/video11
        /dev/video12
        /dev/video18

bcm2835-isp (platform:bcm2835-isp):
        /dev/video13
        /dev/video14
        /dev/video15
        /dev/video16

mmal service 16.1 (platform:bcm2835-v4l2-0):
        /dev/video0

UVC Camera (534d:2109): USB Vid (usb-3f980000.usb-1.5):
        /dev/video1
        /dev/video2

ちなみに...
ラズパイカメラはコーデックも積んでいます
/dev/video0 (= -d 0) のフォーマットリストを見ると H264 があります
今回はffmpegでエンコードする代わりに、これを使おうと思います

pi@raspberrypi:~ $ v4l2-ctl -d 0 --list-formats
ioctl: VIDIOC_ENUM_FMT
        Type: Video Capture

        [0]: 'YU12' (Planar YUV 4:2:0)
        [1]: 'YUYV' (YUYV 4:2:2)
        [2]: 'RGB3' (24-bit RGB 8-8-8)
        [3]: 'JPEG' (JFIF JPEG, compressed)
        [4]: 'H264' (H.264, compressed)
        [5]: 'MJPG' (Motion-JPEG, compressed)
        [6]: 'YVYU' (YVYU 4:2:2)
        [7]: 'VYUY' (VYUY 4:2:2)
        [8]: 'UYVY' (UYVY 4:2:2)
        [9]: 'NV12' (Y/CbCr 4:2:0)
        [10]: 'BGR3' (24-bit BGR 8-8-8)
        [11]: 'YV12' (Planar YVU 4:2:0)
        [12]: 'NV21' (Y/CrCb 4:2:0)
        [13]: 'RX24' (32-bit XBGR 8-8-8-8)

ライブ配信用コマンドラインです
これでライブ配信できます
ストリームURL / ストリームキー に YouTube Studio から取得した値を入れてください

$ raspivid -w 1920 -h 1080 -fps 30 -o - -t 0 -b 2500000 | ffmpeg -re -stream_loop -1 -i no_sound-1.mp3 -f h264 -i - -c:v copy -f flv rtmp://{ ストリームURLを入れる }/{ ストリームキーを入れる }

上記コマンドを実行して、しばらく(1分ほど、場合による)待っていると
YouTube Studio でラズパイから送出されたライブ映像が確認できます

ライブ配信、すごく簡単ですね...

2. [後半-2] (座学) YouTube Live Streaming API における BroadcastsStreams の概念とライフサイクル (飛ばしてもよい)

ここでは座学ということで
YouTube Live Streaming APIBroadcastsStreams がどういう概念なのかを
かるーく説明します

Broadcasts は、YouTube の「番組」にあたるものです
放送前だったり、ライブ放送中だったり、ライブ後にアーカイブされた状態だったりと
いくつかの状態を持ちます
Broadcasts には、それぞれIDがつきます。
これは YouTube を使っている方ならおなじみのID(文字列)で
https://www.youtube.com/watch?v=fEvM-OUbaKs など
いわゆる YouTube URLfEvM-OUbaKs の部分になります

Streams は、ラズパイなどのストリーミング送出機器に対する「ストリーム受信窓口」です
ストリームURLとストリームKEYが設定され
RTMP(RTMPS)の送出先URLになります
ffmpegやOBSなどでは、このストリームURLとストリームKEYを送出先として設定して
YouTubeStreams に向けてライブストリーミングを送り出すことになります

StreamsBroadcast に結び付けて初めて視聴可能となります
この作業を Bind と呼びます
image.png

本記事では BroadcastsStreams は以下のように運用します
すなわち
Broadcasts は都度新規作成する
Stremas は常に同じものを使いまわす
理由は、URL + KEY がいちいち変わると設定が面倒くさいから...
image.png
※ 以下に示す手順は、上記の運用に従ったものになるので、そう思って読んでいってください

3. [後半-3] YouTube Live Streaming APIでライブ配信をする① (準備)

後半-1 の手順で YouTube Studio を利用して行っていた部分を
YouTube Live Streaming API を使って操作してみたいと思います

Broadcasts の作成

まずは Broadcasts を作成します
この時 scheduledStartTime の指定が必要になります
現在時刻から「遠すぎない」未来の時刻の間での指定が必要になるので自動生成しましょう
ACCESS_TOKEN は、前半の手順で取得した ACCESS_TOKEN です
やっと使う時がきました
もし Expire していたら、再度 REFRESH_TOKEN から取得しましょう

$ DATE=`TZ=0 date '+%Y-%m-%dT%H:%M:%S.000Z'`
$ ACCESS_TOKEN={ Access Token を入力 }
$ curl --request POST "https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id,snippet,contentDetails,status" --header "Authorization: Bearer $ACCESS_TOKEN" --header 'Accept: application/json' --header 'Content-Type: application/json' --data '{ "snippet" : { "scheduledStartTime": "'"$DATE"'", "title": "ラズパイ配信テスト" }, "status" : { "privacyStatus": "private" }}' --compressed

実際戻ってくる json はこんな感じです

pi@raspberrypi:~/sidecar/mylinebot $ curl --request POST "https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id,snippet,contentDetails,status" --header "Authorization: Bearer $ACCESS_TOKEN" --header 'Accept: application/json' --header 'Content-Type: application/json' --data '{ "snippet" : { "scheduledStartTime": "'"$DATE"'", "title": "ラズパイ配信テスト" }, "status" : { "privacyStatus": "private" }}' --compressed
{
  "kind": "youtube#liveBroadcast",
  "etag": "xxxxx",
  "id": " ここに Boradcast ID が入っている ", ★★★
  "snippet": {
    "publishedAt": "2023-03-07T01:15:46Z",
    "channelId": "xxxxx",
    "title": "ラズパイ配信テスト",
    ()
    },
    "scheduledStartTime": "2023-03-07T01:15:07Z",
    "isDefaultBroadcast": false,
    "liveChatId": "xxxxx"
  },
  ()
}

このコマンドで表示されるjsonに Broadcast ID が含まれています
メモしておきましょう
この後コマンドの中で頻繁に利用するので環境変数に設定しておきましょう

$ BROADCAST_ID={ Boradcat ID を入力する }

ここからは手順に従って YouTube Live Streaming API のAPIを呼ぶだけなのでどんどん行きます

Stream IDを調べる

ラズパイからの送出先となる Stremas のIDを調べます

$ curl --request GET "https://www.googleapis.com/youtube/v3/liveStreams?part=id,snippet,cdn,status&mine=true" --header "Authorization: Bearer $ACCESS_TOKEN" --header 'Accept: application/json' --header 'Content-Type: application/json' --compressed

こんな json が返ってきます
items の下に id があって、ここに Streams ID が入っています
メモします

pi@raspberrypi:~/sidecar/mylinebot $ curl --request GET "https://www.googleapis.com/youtube/v3/liveStreams?part=id,snippet,cdn,status&mine=true" --header "Authorization: Bearer $ACCESS_TOKEN" --header 'Accept: application/json' --header 'Content-Type: application/json' --compressed
{
  "kind": "youtube#liveStreamListResponse",
  "etag": "XXXXX",
  "pageInfo": {
    "totalResults": 1,
    "resultsPerPage": 5
  },
  "items": [
    {
      "kind": "youtube#liveStream",
      "etag": "XXXXX",
      "id": "ここに Stream ID が入っている", ★★★
      "snippet": {
        "publishedAt": "2020-09-07T00:35:06Z",
        "channelId": "XXXXX",
        "title": "Default stream key",
        "description": "Description for default stream key",
        "isDefaultStream": false
      },
      ()
    }
  ]
}

これも再利用するので環境変数に設定しておきます

$ STREAM_ID={ Stream ID を入力する }

BroadcatsStreams をバインドする

$ curl --request POST "https://www.googleapis.com/youtube/v3/liveBroadcasts/bind?id=$BROADCAST_ID&part=id,snippet,contentDetails,status&streamId=$STREAM_ID" --header "Authorization: Bearer $ACCESS_TOKEN" --header 'Accept: application/json' --header 'Content-Type: application/json' --compressed

Broadcasts のステータスを testing に変更する (ライブ開始の準備の状態にする)

$ curl --request POST "https://youtube.googleapis.com/youtube/v3/liveBroadcasts/transition?broadcastStatus=testing&id=$BROADCAST_ID&part=id&part=snippet&part=contentDetails&part=status" --header "Authorization: Bearer $ACCESS_TOKEN" --header 'Accept: application/json' --header 'Content-Type: application/json' --compressed

4. [後半-4] YouTube Live Streaming APIでライブ配信をする② (配信)

いよいよライブ配信を開始します

● ラズパイからライブ配信を始める (別シェルで実行してください)

$ raspivid -w 1920 -h 1080 -fps 30 -o - -t 0 -b 2500000 | ffmpeg -re -stream_loop -1 -i no_sound-1.mp3 -f h264 -i - -c:v copy -f flv rtmp://{ ストリームURLを入れる }/{ ストリームキーを入れる }

Broadcasts のステータスを live に変更する (ライブ公開状態にする)

$ curl --request POST "https://youtube.googleapis.com/youtube/v3/liveBroadcasts/transition?broadcastStatus=live&id=$BROADCAST_ID&part=id&part=snippet&part=contentDetails&part=status" --header "Authorization: Bearer $ACCESS_TOKEN" --header 'Accept: application/json' --header 'Content-Type: application/json' --compressed

ブラウザで
https://www.youtube.com/watch?v={ Broadcast ID を入力 }
を開くと、ラズパイからのライブ配信が見られるはずです

5. [後半-5] YouTube Live Streaming APIでライブ配信をする② (終了、アーカイブ)

● ラズパイからのストリーミングを止める

ちょっと強引ですがストリーミングに使っているプロセスを kill しちゃいます

$ ps aux | grep raspivid | grep -v grep | grep -v bash | awk '{ print "kill -9", $2 }' | sh
$ ps aux | grep ffmpeg | grep -v grep | grep -v bash | awk '{ print "kill -9", $2 }' | sh

Broadcasts のステータスを complete に変更する (ストリーミングを止めて、アーカイブをする)

$ curl --request POST "https://youtube.googleapis.com/youtube/v3/liveBroadcasts/transition?broadcastStatus=complete&id=$BROADCAST_ID&part=id&part=snippet&part=contentDetails&part=status" --header "Authorization: Bearer $ACCESS_TOKEN" --header 'Accept: application/json' --header 'Content-Type: application/json' --compressed

YouTubeへライブ配信したストリーミングは自動的にアーカイブされ
Broadcasts を明示的に消さないかぎりずっと見られます
URLは
https://www.youtube.com/watch?v={ Broadcast ID を入力 }
です

終わり

お疲れさまでした
これで、YouTube Live の一連の動作を YouTube Live Streaming API から実施できました
後はスクリプト組むなり、コーディングするなりで自動化しましょう

この記事での手順の紹介はここまでです
お付き合いありがとうございました!

気軽にライブ配信できる世の中を目指して
ではでは

参考になる記事

■ とかい育ち.com
YouTubeLiveのイベント配信枠をAPIから作成する
https://tokaisodachi.com/archives/2206

■ Qiita
YouTube Data APIを使ってみる
https://qiita.com/comcha/items/5edda78c917bf70adb63

■ 釣りキチ翔平の備忘録
Google OAuthでAccess Tokenを取得する|Google APIを利用するための準備編
https://poppingcarp.com/google-api_get_access_token/

■ Google公式
YouTube Data APIの概要
https://developers.google.com/youtube/v3/getting-started?hl=ja

EOF

17
15
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
17
15

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?