Posts match “ YouTube ” tag:

授權方式(Auhorization): CC-BY 4.0

English Version

準備

要先申請google的api key
統一到 google developer console

  1. create project 填name和ID
  2. API auth 找到youtube data api 把status 設成 ON
  3. Credentials 申請一組Client ID for web application 擁有Client ID和Client secret準備工作就完成了 !! 注意youtube live streaming api不支援service account,原因是因為必須要存取使用者權限,所以除了service account flow以外都支援。

APIs Explorer

google提供的api 都可以先用api explorer來玩
https://developers.google.com/apis-explorer/

  1. youtube Data API 找到youtube.liveBroadcasts.insert
  2. 將OAuth request 設成 ON
  3. part欄位 snippet,status
  4. request body欄位 可以用add property選擇status跟snippet
    request body
    {
    "snippet": {
    "scheduledEndTime": "2014-04-16T20:00:00.0+08",
    "scheduledStartTime": "2014-04-16T18:00:00.0+08",
    "title": "hero g0v"
    },
    "status": {
    "privacyStatus": "private"
    }
    }
    
    以上都是必填欄位, 注意時間格式為ISO-8601: YYYY-MM-DDThh:mm:ss.sZ

nodejs

google有提供nodejs 的api client
source code
一般熟悉nodejs的人直接npm i googleapis就可以了

流程

  1. 使用Oauth 取得 authorization code
  2. 用auhorization code取得access token
  3. 利用access token存取youtube api
  4. 以下是youtube live stream api的五個步驟
    1. Set up your broadcast
      1. create broadcast (新增現場直播)
      2. create stream (創建串流)
      3. bind broadcast and stream (選取串流)
    2. Claim your content # 這步驟需要取得Content ID API, 沒有的話就是沒辦法設定一些著作權的policy而已
    3. Test (預覽)
      • liveStreams.list 去找剛剛那個stream id, status變成 active時
      • 呼叫livebroadcasts.transition 'testing'
    4. Broadcast (啟動串流直播)
      • 當 test 完成呼叫 呼叫livebroadcasts.transition 'live'
    5. Conclude your broadcast 完成!

步驟詳細內容請參考 Life of a broadcast

新增現場直播

必要參數

part: [snippet, status]
snippet: [title,scheduledStartTime,scheduledEndTime]
status: [privacyStatus]

err, broadcast <- client.youtube.live-broadcasts.insert part: 'snippet,status', req-broadcast
  .with-auth-client auth
  .execute
return console.log err if err
console.log broadcast

目前會看到成功回傳

response body
{ kind: 'youtube#liveBroadcast',
  etag: '"X98aQHqGvPBJLZLOiSGUHCM9jnE/2kEP-c4VUkPHY301QBKEBcJJRMA"',
  id: 'v-MKk0Z3HB4',
  snippet:
   { publishedAt: '2014-04-16T05:23:58.000Z',
     channelId: 'UCWDNcRqKYS8PjGn2Z7RUocg',
     title: 'test',
     description: '',
     thumbnails: { default: [Object], medium: [Object], high: [Object] },
     scheduledStartTime: '2014-05-16T21:00:00.000Z',
     scheduledEndTime: '2014-05-17T00:00:00.000Z' },
  status:
   { lifeCycleStatus: 'created',
     privacyStatus: 'private',
     recordingStatus: 'notRecording' } }

可以到 youtube 活動現場看到剛剛新增的event

創建串流

必要參數

part: [snippet, cdn]
snippet: [title]
cdn: [format, ingestionType]

err, stream <- client.youtube.live-streams.insert part: 'snippet,cdn', req-stream
  .with-auth-client auth
  .execute
return console.log err if err
console.log stream

目前會看到成功回傳

livesteam response body
{

 "kind": "youtube#liveStream",
 "etag": "\"X98aQHqGvPBJLZLOiSGUHCM9jnE/F8dDAvNbcjro8PFQe4H82hilSmQ\"",
 "id": "WDNcRqKYS8PjGn2Z7RUocg1397629864085436",
 "snippet": {
  "publishedAt": "2014-04-16T06:31:04.000Z",
  "channelId": "UCWDNcRqKYS8PjGn2Z7RUocg",
  "title": "test g0v",
  "description": ""
 },
 "cdn": {
  "format": "720p",
  "ingestionType": "rtmp",
  "ingestionInfo": {
   "streamName": "ly.forever.rkx0-bwp3-7fy0-9ykd",
   "ingestionAddress": "rtmp://a.rtmp.youtube.com/live2",
   "backupIngestionAddress": "rtmp://b.rtmp.youtube.com/live2?backup=1"
  }
 }
}

選取串流

必要參數

part: [id,contentDetails]
id: [broadcast id]
streamId: [stream id]

err, bind <- client.youtube.live-broadcasts.bind part: 'id,contentDetails', id: video-id, stream-id: stream-id
  .with-auth-client auth
  .execute
console.log bind

目前成功會回傳

livebroadcast.bind response body
{

 "kind": "youtube#liveBroadcast",
 "etag": "\"X98aQHqGvPBJLZLOiSGUHCM9jnE/B5DR-1fKyXag5mlIwZ6Tqc9-ysk\"",
 "id": "v-MKk0Z3HB4"
}

使用ffmpeg 將影片傳到串流上

new fluent-ffmpeg source: 'rtmp://cp49989.live.edgefcs.net:1935/live/streamRM1@2564'
  .with-video-codec 'libx264'
  .with-audio-codec 'libfaac'
  .with-audio-bitrate '128k'
  .with-audio-channels 1
  .with-audio-frequency 44100
  .with-size '426x240'
  .with-fps 30
  .to-format 'flv'
  .add-options ['-g 1', '-force_key_frames 2']
  .on 'start' -> console.log 'FFmpeg start with ' + it
  .on 'progress' ->
    err, streams <- client.youtube.live-streams.list part: 'id,status', id: stream-id
      .with-auth-client auth
      .execute
    err, test <- transit-it auth, client, 'testing'
    err, live <- transit-it auth, client, 'live'
    console.log live.status if live
  .on 'end' -> console.log 'FFmpeg end.'
  .write-to-stream stream-url

測試直播

err, it <- client.youtube.live-broadcasts.transition broadcast-status: 'testing', id: video-id, part: 'id,status,contentDetails'
    .with-auth-client auth
    .execute
consoel.log it

啟動串流直播

err, it <- client.youtube.live-broadcasts.transition broadcast-status: 'live', id: video-id, part: 'id,status,contentDetails'
    .with-auth-client auth
    .execute
consoel.log it

完整程式碼

ffmpeg的詳細指令

$ ffmpeg -i rtmp://cp49989.live.edgefcs.net:1935/live/streamRM1@2564 -vcodec libx264 -maxrate 700k -r 30 -s 426x240 -g 0 -acodec libvo_aacenc -ab 128k -ac 1 -ar 44100 -f flv rtmp://

$ ffmpeg -i rtmp://h264media02.ly.gov.tw:1935/live07/300K_Live -vcodec libx264 -maxrate 700k -minrate 300k -r 30 -s 426x240 -g 1 -force_key_frames 2 -acodec libvo_aacenc -ab 128k -ac 1 -ar 44100 -f flv rtmp://

心得

google的document很完整,但還是容易霧裡看花,一下就迷失了。
至少比irccloud還要去猜api好多了~不愧是google~
但是nodejs sample在document裡面都沒有,幸好github上面的都很完整!
googleapis example
經過這次經驗,最後有抓到如何快速看google api document的訣竅了 :)