如何將live stream發佈到Youtube

1.搭建開發環境

  1. 申請Google賬號
  2. 登錄Google賬號,進入創作者工作室。進入直播欄目,打開個人賬戶直播功能
  3. 進入google develop console 
    1. a. 創建新項目 
      b. 啓用YouTube Data API v3 
      c. 創建憑據,Oauth 客戶端 ID,選擇網頁客戶端。輸入名稱,重定向URL,點擊創建。完成以後就可以獲取一個json文件。裏面就有需要的secrete_id。保存該json文件,會放入Android 工程中。 
      d.如果完全沒有使用過Youtube API可以下載youtube-api-samples。或者觀看教學影片:YouTube Developers Live: Setting up your Java IDE for Google API samples

    2.獲取用戶授權

    (Java code,更加詳細的授權,會在另一篇文章中呈現)

    a.需要導入準備工作中下載的client_secrets.json文件。裏面有client_id和client_secret。調用GoobleOAuth.login函數即可獲得OAuth2AccessToken;

    GoogleOAuth.login(VrSpherePreviewActivity.this)
    .setClientId(clientSecrets.getDetails().getClientId())
    .setClientSecret(clientSecrets.getDetails().getClientSecret())
    .setAdditionalScopes("https://www.googleapis.com/auth/youtube")
    .setRedirectUri("http://localhost:8080")
    .setCallback(new OnLoginCallback())
    .init();
    

    獲取token成功之後,我們就可以在OnLoginCallback()中得到OAuth2AccessToken token,其中包含token 和 fresh_token;

    b.調用 Auth.authorize(clientSecrets, token);來獲取Credential相關數據。 
    c.最後,調用下面的程序就可以通過credential數據來授權youtube賬戶下的Channel和live相關的操作;

    youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT, Auth.JSON_FACTORY, credential)
            .setApplicationName("youtube-cmdline-createbroadcast-sample").build();
    

    3.建立LiveBroadCast頻道

    它的作用是在直播活動中建立一個頻道。有頻道的名稱、開始和結束時間、頻道的狀態等信息。頻道建立好以後,可以通過YouTube.LiveBroadcasts.Insert插入頻道的一些屬性。比如我們代碼中就插入了snippet,status,contentDetails三種屬性:

    Property Introduction
    snippet The snippet object contains basic details about the event, including its title, description, start time, and end time.
    status The status object contains information about the event’s status.
    contentDetails The contentDetails object contains information about the event’s video content, such as whether the content can be shown in an embedded video player or if it will be archived and therefore available for viewing after the event has concluded.

    具體的屬性信息可以參考Youtube的官方文檔,有詳細的介紹:https://developers.google.com/youtube/v3/live/docs/liveBroadcasts

    我們需要設定的一些屬性:

    • snippet.title
    • snippet.actualStartTime
    • snippet.scheduledStartTime
    • snippet.scheduledEndTime
    • status.privacyStatus
    • contentDetails.projection

    設置完成之後,通過HTTP POST將請求發送給服務器。

    POST https://www.googleapis.com/youtube/v3/liveBroadcasts
    • 1

    HTTP:

    POST /youtube/v3/liveBroadcasts?part=id,snippet,status,contentDetails HTTP/1.1
            Host: www.googleapis.com
            Content-Type: application/json
            Authorization: Bearer ya29.Ci_XA_vpHXHqVh_0mUJ3DFjpNwvfy1XLsg2pRBDGXYIlSsyBOUgtdVOOhaudddfJTg
            Cache-Control: no-cache
            Postman-Token: 29293451-38a3-306b-35ef-c652b4c1d3e7
            {
              "snippet": {
                "title": "TestLiveCode",
                "actualStartTime": "2017-01-19T06:14:40.000Z",
                "scheduledStartTime": "2017-01-19T06:14:40.000Z",
                "scheduledEndTime": "2017-01-19T20:14:40.000Z"
              },
              "status": {
                "privacyStatus": "public"
              },
              "contentDetails": {
                "projection": "360"
              }
          }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    獲得Response,得到LiveBroadCasts信息:

    {
        "kind": "youtube#liveBroadcast",
        "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/RS5N6l3SydSyJtxvNL0Y1C1OYs4\"",
        "id": "TgaR-sHrnjM",
        "snippet": { "publishedAt": "2017-01-19T07:30:15.000Z", "channelId": "UCl75gUJzbdbrzNDWlu4nYkA", "title": "TestLiveCode", "description": "", "thumbnails": { "default": { "url": "https://i.ytimg.com/vi/TgaR-sHrnjM/default_live.jpg", "width": 120, "height": 90 }, "medium": { "url": "https://i.ytimg.com/vi/TgaR-sHrnjM/mqdefault_live.jpg", "width": 320, "height": 180 }, "high": { "url": "https://i.ytimg.com/vi/TgaR-sHrnjM/hqdefault_live.jpg", "width": 480, "height": 360 } }, "scheduledStartTime": "2017-01-19T07:14:30.000Z", "scheduledEndTime": "2017-01-19T20:14:40.000Z", "isDefaultBroadcast": false, "liveChatId": "Cg0KC1RnYVItc0hybmpN" },
        "status": { "lifeCycleStatus": "created", "privacyStatus": "public", "recordingStatus": "notRecording" },
        "contentDetails": { "monitorStream": { "enableMonitorStream": true, "broadcastStreamDelayMs": 0, "embedHtml": "<iframe width=\"425\" height=\"344\" src=\"https://www.youtube.com/embed/TgaR-sHrnjM?autoplay=1&livemonitor=1\" frameborder=\"0\" allowfullscreen></iframe>" }, "enableEmbed": true, "enableDvr": true, "enableContentEncryption": false, "startWithSlate": false, "recordFromStart": true, "enableClosedCaptions": false, "closedCaptionsType": "closedCaptionsDisabled", "enableLowLatency": false, "projection": "360" } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Java

        // Create a snippet with the title and scheduled start and end
        // times for the broadcast. Currently, those times are hard-coded.
        LiveBroadcastSnippet broadcastSnippet = new LiveBroadcastSnippet();
        broadcastSnippet.setTitle(title);
        long time = System.currentTimeMillis();
        broadcastSnippet.setPublishedAt(new DateTime(time));
        broadcastSnippet.setScheduledStartTime(new DateTime(time));
        broadcastSnippet.setScheduledEndTime(new DateTime(time+60*60*1000));
    
        // Set the broadcast's privacy status to "private". See:
        // https://developers.google.com/youtube/v3/live/docs/liveBroadcasts#status.privacyStatus
        LiveBroadcastStatus status = new LiveBroadcastStatus();
        status.setPrivacyStatus("public");
    
        LiveBroadcast broadcast = new LiveBroadcast();
        broadcast.setKind("youtube#liveBroadcast");
        broadcast.setSnippet(broadcastSnippet);
        broadcast.setStatus(status);
    
        LiveBroadcastContentDetails contentDetails = new LiveBroadcastContentDetails();
        contentDetails.setProjection("360"); 
        broadcast.setContentDetails(contentDetails);
    
        // Construct and execute the API request to insert the broadcast.
        YouTube.LiveBroadcasts.Insert liveBroadcastInsert =
                youtube.liveBroadcasts().insert("snippet,status,contentDetails", broadcast);
        liveBroadcast = liveBroadcastInsert.execute();
    

    C

    CURL *hnd = curl_easy_init();
    
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id%2Csnippet%2Cstatus");
    
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "postman-token: 97d63c4d-8e5d-7c09-9de8-66b7db42c23b");
    headers = curl_slist_append(headers, "cache-control: no-cache");
    headers = curl_slist_append(headers, "authorization: Bearer ya29.Ci_XA_vpHXHqVh_0mUJ3DFjpNwvfy1XLsg2pRBDGXYIlSsyBOUgtdVOOhaudnKfJTg");
    headers = curl_slist_append(headers, "content-type: application/json");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
    
    curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\n  \"snippet\": {\n    \"title\": \"TestLiveCode\",\n    \"actualStartTime\": \"2017-01-19T06:14:40.000Z\",\n    \"scheduledStartTime\": \"2017-01-19T06:14:40.000Z\",\n    \"scheduledEndTime\": \"2017-01-19T20:14:40.000Z\"\n  },\n  \"status\": {\n    \"privacyStatus\": \"public\"\n  },\n  \"contentDetails\": {\n    \"projection\": \"360\"\n  }\n}");
    
    CURLcode ret = curl_easy_perform(hnd);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    4.建立streaming通道

    建立頻道的streaming通道。有了這個streaming通道,我們就可以通過該通道向頻道發送直播視頻。 
    需要設置一些streaming的屬性:snippet,cdn ,status

    Property Introduction
    snippet The snippet object contains basic details about the stream, including its channel, title, and description
    cdn The cdn object defines the live stream’s content delivery network (CDN) settings. These settings provide details about the manner in which you stream your content to YouTube.
    status The status object contains information about live stream’s status.

    具體的屬性信息可以參考Youtube的官方文檔,有詳細的介紹:https://developers.google.com/youtube/v3/live/docs/liveStreams

    我們需要設定的一些屬性:

    • snippet.title
    • cdn.ingestionInfo.streamName
    • cdn.ingestionInfo.ingestionAddress
    • cdn.resolution
    • cdn.ingestionType
    • cdn.frameRate

    設置完成之後,通過HTTP POST將請求發送給服務器。

    POST https://www.googleapis.com/youtube/v3/liveStreams
    • 1

    HTTP

    POST //www.googleapis.com/youtube/v3/liveStreams?part=snippet,cdn HTTP/1.1
    Host: POST https:
    Content-Type: application/json
    Authorization: Bearer ya29.Ci_XA_vpHXHqVh_0mUJ3DFjpNwvfy1XLsg2pRBDGXYIlSsyBOUgtdVOOhaudnKfJTg
    Cache-Control: no-cache
    Postman-Token: b3d3157d-9915-c084-2d43-85d9bdd74a88
    
    { "snippet": { "title": "TestStream" }, "cdn": { "ingestionInfo": { "streamName": "MyTestStream", "ingestionAddress": "rtmp://a.rtmp.youtube.com/live2" }, "resolution": "720p", "ingestionType": "rtmp" "frameRate": "30fps" } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    獲得Response,得到LiveStreams的信息

    {
        "kind": "youtube#liveStream",
        "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/OsA5SrDlgCAfnSbwtDkNYyeBko0\"",
        "id": "l75gUJzbdbrzNDWlu4nYkA1484811227264011",
        "snippet": { "publishedAt": "2017-01-19T07:33:47.000Z", "channelId": "UCl75gUJzbdbrzNDWlu4nYkA", "title": "TestStream", "description": "", "isDefaultStream": false },
        "cdn": { "format": "720p", "ingestionType": "rtmp", "ingestionInfo": { "streamName": "qhvu-315p-y3wr-5uf7", "ingestionAddress": "rtmp://a.rtmp.youtube.com/live2", "backupIngestionAddress": "rtmp://b.rtmp.youtube.com/live2?backup=1" }, "resolution": "720p", "frameRate": "30fps" } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    streamName + ingestionAddress 則是我們的推送地址:rtmp://a.rtmp.youtube.com/live2/qhvu-315p-y3wr-5uf7

    Java

    // Create a snippet with the video stream's title.
    LiveStreamSnippet streamSnippet = new LiveStreamSnippet();
    streamSnippet.setTitle(title);
    
    IngestionInfo ingestionInfo = new IngestionInfo();
    ingestionInfo.setStreamName("Education");
    //此Rtmp位址為固定,不需改變
    //Youtube提供給我們打入Stream訊號的Rtmp Server
    ingestionInfo.setIngestionAddress("rtmp://a.rtmp.youtube.com/live2");
    
    // Define the content distribution network settings for the
    // video stream. The settings specify the stream's format and
    // ingestion type. See:
    // https://developers.google.com/youtube/v3/live/docs/liveStreams#cdn
    CdnSettings cdnSettings = new CdnSettings();
    cdnSettings.setIngestionInfo(ingestionInfo);
    cdnSettings.setFormat("720p");
    cdnSettings.setIngestionType("rtmp");
    
    LiveStream stream = new LiveStream();
    stream.setKind("youtube#liveStream");
    stream.setSnippet(streamSnippet);
    stream.setCdn(cdnSettings);
    
    // Construct and execute the API request to insert the stream.
    YouTube.LiveStreams.Insert liveStreamInsert =
            youtube.liveStreams().insert("snippet,cdn", stream);
    liveStream = liveStreamInsert.execute();
    push_addr = liveStream.getCdn().getIngestionInfo().getIngestionAddress() + "/" + liveStream.getCdn()
            .getIngestionInfo().getStreamName(); ==>此處就是我們獲取的stream的推送地址
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31

    C

    CURL *hnd = curl_easy_init();
    
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(hnd, CURLOPT_URL, "http://post/%20https://www.googleapis.com/youtube/v3/liveStreams?part=snippet%2Ccdn");
    
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "postman-token: d3a48a2e-8d19-3c22-932d-9c615a2ffafa");
    headers = curl_slist_append(headers, "cache-control: no-cache");
    headers = curl_slist_append(headers, "authorization: Bearer ya29.Ci_XA_vpHXHqVh_0mUJ3DFjpNwvfy1XLsg2pRBDGXYIlSsyBOUgtdVOOhaudnKfJTg");
    headers = curl_slist_append(headers, "content-type: application/json");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
    
    curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "{\n  \"snippet\": {\n    \"title\": \"TestStream\"\n  },\n  \"cdn\": {\n    \"ingestionInfo\": {\n      \"streamName\": \"MyTestStream\",\n      \"ingestionAddress\": \"rtmp://a.rtmp.youtube.com/live2\"\n    },\n    \"resolution\": \"720p\",\n    \"ingestionType\": \"rtmp\"\n  }\n}");
    
    CURLcode ret = curl_easy_perform(hnd);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    5.綁定LiveBroadcast和LiveStreams

    將前面所建立的broadcast對象和stream對象進行綁定。一個broadcast只能有一個stream來源,但是一個stream來源可以同時綁定多個broadcast頻道。

    需要的設置的屬性:

    • Id:LiveBroadCast的ID
    • streamId:LiveStreams的ID 
      設置完成之後,通過HTTP POST將請求發送給服務器。
    POST https://www.googleapis.com/youtube/v3/liveBroadcasts/bind
    • 1

    HTTP

    POST /youtube/v3/liveBroadcasts/bind?part=id,contentDetails&amp;id=TgaR-sHrnjM&amp;streamId=l75gUJzbdbrzNDWlu4nYkA1484811227264011 HTTP/1.1
    Host: www.googleapis.com
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
    Authorization: Bearer ya29.GlvYAxeqIoZCYHcg34TYX_cdtlFxk_9FVmw-Xlbf9uZhk_Jf5VeQ2RBPjDD-wcjxvLLvk4iG6ZZiFrySHzwHxsuasDPagrJVeVoQwYhods-vzXNM1wiZ67-ofWSN
    Cache-Control: no-cache
    Postman-Token: d936a1fc-ca1c-8cf8-7950-837fcd297928
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    獲得Response,得到Bind的信息

    {
        "kind": "youtube#liveBroadcast",
        "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/1B1cxYwwGl93plqlVa67-0ilytE\"",
        "id": "TgaR-sHrnjM",
        "contentDetails": { "boundStreamId": "l75gUJzbdbrzNDWlu4nYkA1484811227264011", "boundStreamLastUpdateTimeMs": "2017-01-19T07:33:47.306Z", "monitorStream": { "enableMonitorStream": true, "broadcastStreamDelayMs": 0, "embedHtml": "<iframe width=\"425\" height=\"344\" src=\"https://www.youtube.com/embed/TgaR-sHrnjM?autoplay=1&livemonitor=1\" frameborder=\"0\" allowfullscreen></iframe>" }, "enableEmbed": true, "enableDvr": true, "enableContentEncryption": false, "startWithSlate": false, "recordFromStart": true, "enableClosedCaptions": false, "closedCaptionsType": "closedCaptionsDisabled", "enableLowLatency": false, "projection": "360" } }
    • 1
    • 2
    • 3
    • 4
    • 5

    分享給用戶觀看的地址則是:”https://www.youtube.com/watch?v= + id

    Java

    // Construct and execute a request to bind the new broadcast and stream.
    YouTube.LiveBroadcasts.Bind liveBroadcastBind =
            youtube.liveBroadcasts().bind(liveBroadcast.getId(), "id,contentDetails");
    liveBroadcastBind.setStreamId(liveStream.getId());
    liveBroadcast = liveBroadcastBind.execute();
    
    String share_addr = "https://www.youtube.com/watch?v=" + liveBroadcast.getId(); ==>此處即是我們分享給觀衆的觀看地址。
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    C

    CURL *hnd = curl_easy_init();
    
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://www.googleapis.com/youtube/v3/liveBroadcasts/bind?part=id%2CcontentDetails&id=TgaR-sHrnjM&streamId=l75gUJzbdbrzNDWlu4nYkA1484811227264011");
    
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "postman-token: 2008a012-a4e6-991e-e977-a9c7095b0b89");
    headers = curl_slist_append(headers, "cache-control: no-cache");
    headers = curl_slist_append(headers, "authorization: Bearer ya29.GlvYAxeqIoZCYHcg34TYX_cdtlFxk_9FVmw-Xlbf9uZhk_Jf5VeQ2RBPjDD-wcjxvLLvk4iG6ZZiFrySHzwHxsuasDPagrJVeVoQwYhods-vzXNM1wiZ67-ofWSN");
    headers = curl_slist_append(headers, "content-type: application/json");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
    
    CURLcode ret = curl_easy_perform(hnd);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    到這裏,創建頻道,獲取視頻流推送地址,以及用戶觀看地址都已經準備好了。此時我們就可以通過推流工具,或者自己的推流方法來完成向直播頻道推流。在Youtube 直播欄目下面,進入直播活動,我們就可以看到已經創建的頻道。點擊進去以後,可以看到當前的頻道是否有接收到碼流。如果現實正常,則表示我們整個直播的頻道和視頻流都已經建立成功。只需要再下一步將我們的視頻流播放給觀衆就可以了。

    6.切換liveBroadcast狀態

    當我們建立好頻道並且頻道已經能夠成功接收到穩定的碼流數據之後。我們就可以通過獲取stream的狀態來獲取碼流是否正常。如下代碼就是檢測當前頻道是否有穩定的碼流上傳:

    使用HTTP GET來獲取liveBroadcast狀態

    GET https://www.googleapis.com/youtube/v3/liveBroadcasts
    • 1

    HTTP

    GET /youtube/v3/liveStreams?part=id,status&id=l75gUJzbdbrzNDWlu4nYkA1484811227264011 HTTP/1.1
    Host: www.googleapis.com
    Authorization: Bearer ya29.GlvYAxT6PZjpk_prTaPm2clOVaIPbSYFrYc37I9PIDtJ-nYiT5bCevA24vkUezhoD-_ufMP3Yi2Bte6guECX0QRIknVIby4RUXj8Ms73primnytBoOfVNnGD7ckF
    Cache-Control: no-cache
    Postman-Token: 53301af4-fada-9f59-1568-be32d824aecc
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Response

    {
        "kind": "youtube#liveStreamListResponse",
        "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/t4CVyYZj7CiWAqXNBYsuscwbjZk\"",
        "pageInfo": { "totalResults": 0, "resultsPerPage": 5 },
        "items": [ { "kind": "youtube#liveStream", "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/oTGzu9UF_NhJNIkjGpqqg_rpX-I\"", "id": "l75gUJzbdbrzNDWlu4nYkA1484811227264011", "status": { "streamStatus": "active", "healthStatus": { "status": "bad", "configurationIssues": [ { "type": "videoResolutionUnsupported", "severity": "error", "reason": "Unsupported resolution", "description": "You need to change the video resolution. The current resolution is (320x240), which is not supported for this configuration. The expected video resolution is (1280x720)." }, { "type": "bitrateLow", "severity": "warning", "reason": "Video output low", "description": "The stream's current bitrate (592.00 Kbps) is lower than the recommended bitrate. We recommend that you use a stream bitrate of 2500 Kbps." }, { "type": "audioBitrateLow", "severity": "info", "reason": "Check audio settings", "description": "The audio stream's current bitrate (96.00 Kbps) is lower than the recommended bitrate. We recommend that you use an audio stream bitrate of 128 Kbps." }, { "type": "gopSizeOver", "severity": "info", "reason": "Check video settings", "description": "Please use a keyframe frequency of four seconds or less. Currently, keyframes are not being sent often enough, which can cause buffering. The current keyframe frequency is 5.0 seconds. Note that ingestion errors can cause incorrect GOP (group of pictures) sizes." } ] } } } ] }
    • 1
    • 2
    • 3
    • 4
    • 5

    從Response裏面的 “streamStatus”字段可以看出目前stream已經是處於”active”狀態,表示目前我們LiveStreams已經可以收到穩定的視頻流了。

    Java

    liveStreamRequest = youtube.liveStreams()
            .list("id,status")
            .setId(liveBroadcast.getContentDetails()
                    .getBoundStreamId());
    LiveStreamListResponse returnedList = liveStreamRequest.execute();
    List<LiveStream> liveStreams = returnedList.getItems();
    if (liveStreams != null && liveStreams.size() > 0) {
        LiveStream liveStream = liveStreams.get(0);
        if (liveStream != null)
            while (!liveStream.getStatus().getStreamStatus()
                    .equals("active")) {
                Thread.sleep(1000);
                returnedList = liveStreamRequest.execute();
                liveStreams = returnedList.getItems();
                liveStream = liveStreams.get(0);
            }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    C

    CURL *hnd = curl_easy_init();
    
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://www.googleapis.com/youtube/v3/liveStreams?part=id%2Cstatus&id=l75gUJzbdbrzNDWlu4nYkA1484811227264011");
    
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "postman-token: a6337852-8b07-703f-df71-e4c8a0e36060");
    headers = curl_slist_append(headers, "cache-control: no-cache");
    headers = curl_slist_append(headers, "authorization: Bearer ya29.GlvYAxT6PZjpk_prTaPm2clOVaIPbSYFrYc37I9PIDtJ-nYiT5bCevA24vkUezhoD-_ufMP3Yi2Bte6guECX0QRIknVIby4RUXj8Ms73primnytBoOfVNnGD7ckF");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
    
    CURLcode ret = curl_easy_perform(hnd);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    當我們等到stream的狀態爲“Active”的時候。則表示碼流正常。此時離用戶能夠看到直播的視頻還差兩步: 
    a.轉換頻道的狀態爲testing,此時我們可以讓頻道進入測試狀態。用於直播發布者預覽和檢測直播視頻。注意此時用戶是沒有辦法看到直播畫面的。

    使用HTTP POST來切換liveBroadcast狀態:

    POST https://www.googleapis.com/youtube/v3/liveBroadcasts/transition
    • 1

    HTTP

    POST /youtube/v3/liveBroadcasts/transition?broadcastStatus=testing&amp;id=TgaR-sHrnjM&amp;part=id,snippet,contentDetails,status HTTP/1.1
    Host: www.googleapis.com
    Authorization: Bearer ya29.GlvYAxT6PZjpk_prTaPm2clOVaIPbSYFrYc37I9PIDtJ-nYiT5bCevA24vkUezhoD-_ufMP3Yi2Bte6guECX0QRIknVIby4RUXj8Ms73primnytBoOfVNnGD7ckF
    Cache-Control: no-cache
    Postman-Token: db9e406a-876e-9cc6-21e9-9713f7e5828e
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Response

    {
        "kind": "youtube#liveBroadcast",
        "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/nNn7HZoSfMyCoMfqBvaAw1FEgdA\"",
        "id": "8jD-N6GIlkA",
        "snippet": { "publishedAt": "2017-01-19T09:02:42.000Z", "channelId": "UCl75gUJzbdbrzNDWlu4nYkA", "title": "TestLiveCode", "description": "", "thumbnails": { "default": { "url": "https://i.ytimg.com/vi/8jD-N6GIlkA/default_live.jpg", "width": 120, "height": 90 }, "medium": { "url": "https://i.ytimg.com/vi/8jD-N6GIlkA/mqdefault_live.jpg", "width": 320, "height": 180 }, "high": { "url": "https://i.ytimg.com/vi/8jD-N6GIlkA/hqdefault_live.jpg", "width": 480, "height": 360 } }, "scheduledStartTime": "2017-01-19T08:14:30.000Z", "scheduledEndTime": "2017-01-19T20:14:40.000Z", "isDefaultBroadcast": false, "liveChatId": "Cg0KCzhqRC1ONkdJbGtB" },
        "status": { "lifeCycleStatus": "testStarting", "privacyStatus": "public", "recordingStatus": "notRecording" },
        "contentDetails": { "boundStreamId": "l75gUJzbdbrzNDWlu4nYkA1484816504294010", "boundStreamLastUpdateTimeMs": "2017-01-19T09:01:44.342Z", "monitorStream": { "enableMonitorStream": true, "broadcastStreamDelayMs": 0, "embedHtml": "<iframe width=\"425\" height=\"344\" src=\"https://www.youtube.com/embed/8jD-N6GIlkA?autoplay=1&livemonitor=1\" frameborder=\"0\" allowfullscreen></iframe>" }, "enableEmbed": true, "enableDvr": true, "enableContentEncryption": false, "startWithSlate": false, "recordFromStart": true, "enableClosedCaptions": false, "closedCaptionsType": "closedCaptionsDisabled", "enableLowLatency": false, "projection": "360" } }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    Java

    //the broadcast cann't transition the status from ready to live directly,
    //it must change to testing first and then live.
    YouTube.LiveBroadcasts.Transition broadCastTestingRequest = youtube
            .liveBroadcasts().transition("testing",
                    liveBroadcast.getId(), "id,snippet,contentDetails,status");
    liveBroadcast = broadCastTestingRequest.execute();
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    C

    CURL *hnd = curl_easy_init();
    
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://www.googleapis.com/youtube/v3/liveBroadcasts/transition?broadcastStatus=testing&id=TgaR-sHrnjM&part=id%2Csnippet%2CcontentDetails%2Cstatus");
    
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "postman-token: 96da5833-3923-2bbe-e453-1c29efcf8973");
    headers = curl_slist_append(headers, "cache-control: no-cache");
    headers = curl_slist_append(headers, "authorization: Bearer ya29.GlvYAxT6PZjpk_prTaPm2clOVaIPbSYFrYc37I9PIDtJ-nYiT5bCevA24vkUezhoD-_ufMP3Yi2Bte6guECX0QRIknVIby4RUXj8Ms73primnytBoOfVNnGD7ckF");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
    
    CURLcode ret = curl_easy_perform(hnd);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    b.當broadcast的狀態變成testing之後。我們需要將狀態切換成爲“live”,此時用戶就可以看到直播畫面。

    使用HTTP POST切換liveBroadCast狀態從testing到live

    POST https://www.googleapis.com/youtube/v3/liveBroadcasts/transition
    • 1

    HTTP

    POST /youtube/v3/liveBroadcasts/transition?broadcastStatus=live&amp;id=TgaR-sHrnjM&amp;part=id,snippet,contentDetails,status HTTP/1.1
    Host: www.googleapis.com
    Authorization: Bearer ya29.GlvYAxT6PZjpk_prTaPm2clOVaIPbSYFrYc37I9PIDtJ-nYiT5bCevA24vkUezhoD-_ufMP3Yi2Bte6guECX0QRIknVIby4RUXj8Ms73primnytBoOfVNnGD7ckF
    Cache-Control: no-cache
    Postman-Token: 65b123be-7641-8561-56fa-11f3c1f53193
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    Java

    YouTube.LiveBroadcasts.Transition transitionRequest = youtube.liveBroadcasts().transition("live", liveBroadcast.getId(), "status");
    liveBroadcast = transitionRequest.execute();
    • 1
    • 2

    C

    CURL *hnd = curl_easy_init();
    
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "POST");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://www.googleapis.com/youtube/v3/liveBroadcasts/transition?broadcastStatus=live&id=TgaR-sHrnjM&part=id%2Csnippet%2CcontentDetails%2Cstatus");
    
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "postman-token: cb2eb41c-803e-e1ec-d0f9-419772850ff5");
    headers = curl_slist_append(headers, "cache-control: no-cache");
    headers = curl_slist_append(headers, "authorization: Bearer ya29.GlvYAxT6PZjpk_prTaPm2clOVaIPbSYFrYc37I9PIDtJ-nYiT5bCevA24vkUezhoD-_ufMP3Yi2Bte6guECX0QRIknVIby4RUXj8Ms73primnytBoOfVNnGD7ckF");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
    
    CURLcode ret = curl_easy_perform(hnd);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    需要注意的有兩個地方:1.頻道的狀態轉換必須是active->testing->live。不能直接從active轉爲live。2.必須要等待broadcast的狀態變成testing之後,才能進行testing->live的轉換。所以必須進行一個testing狀態轉換完成的一個確認,如下代碼即可:

    使用HTTP GET來獲取liveBroadcast狀態:

    GET https://www.googleapis.com/youtube/v3/liveBroadcasts
    • 1

    HTTP

    GET /youtube/v3/liveBroadcasts?part=id,status&amp;id=TgaR-sHrnjM HTTP/1.1
    Host: www.googleapis.com
    Authorization: Bearer ya29.GlvYA7oXl3IVdI4Bok9jyXC4eXhOzm98oja33jCdrRClc49ie7lOm8inRprZ9qAYyEf7OpsekQUTOarlip-DvY1gewZQGKeW1G1jTWR6djxxpTi4hGmQzSzEOadJ
    Cache-Control: no-cache
    Postman-Token: cd8dada9-5a1b-bab2-611a-c515bbc9c6d7
    • 1
    • 2
    • 3
    • 4
    • 5

    Response

    {
        "kind": "youtube#liveBroadcastListResponse",
        "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/absIVeqkZihPc-0pJMCYTpR5yjU\"",
        "pageInfo": { "totalResults": 0, "resultsPerPage": 5 },
        "items": [ { "kind": "youtube#liveBroadcast", "etag": "\"gMxXHe-zinKdE9lTnzKu8vjcmDI/xrp9a15kZwGJVPtt4AT1OHJjXPw\"", "id": "TgaR-sHrnjM", "status": { "lifeCycleStatus": "testStarting", "privacyStatus": "public", "recordingStatus": "notRecording" } } ] }
    • 1
    • 2
    • 3
    • 4
    • 5

    從Response得到的”lifeCycleStatus”字段可以看到目前的狀態爲”testStarting”,表示正在切換testing狀態中。需要等到”lifeCycleStatus”: “testing”,則表示狀態已經切換完成,可以繼續從testing 向 live狀態切換。

    Java

    liveBroadRequest = youtube.liveBroadcasts().list("id,status");
    liveBroadRequest.setBroadcastStatus("all");
    
    LiveBroadcastListResponse liveBroadcastResponse = liveBroadRequest.execute();
    List<LiveBroadcast> returnedList = liveBroadcastResponse.getItems();
    if (returnedList != null && returnedList.size() > 0) {
        liveBroadcastReq = returnedList.get(0);
        if (liveBroadcastReq != null)
            while (!liveBroadcastReq.getStatus().getLifeCycleStatus().equals("testing")) {
                Thread.sleep(1000);
                AppLog.d("Error","publish broadcast - getLifeCycleStatus: " + liveBroadcastReq.getStatus().getLifeCycleStatus());
                liveBroadcastResponse = liveBroadRequest.execute();
                returnedList = liveBroadcastResponse.getItems();
                liveBroadcastReq = returnedList.get(0);
            }
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    C

    CURL *hnd = curl_easy_init();
    
    curl_easy_setopt(hnd, CURLOPT_CUSTOMREQUEST, "GET");
    curl_easy_setopt(hnd, CURLOPT_URL, "https://www.googleapis.com/youtube/v3/liveBroadcasts?part=id%2Cstatus&id=TgaR-sHrnjM");
    
    struct curl_slist *headers = NULL;
    headers = curl_slist_append(headers, "postman-token: bf3a9e6f-52ae-e159-a2ad-cc81c979c68e");
    headers = curl_slist_append(headers, "cache-control: no-cache");
    headers = curl_slist_append(headers, "authorization: Bearer ya29.GlvYA7oXl3IVdI4Bok9jyXC4eXhOzm98oja33jCdrRClc49ie7lOm8inRprZ9qAYyEf7OpsekQUTOarlip-DvY1gewZQGKeW1G1jTWR6djxxpTi4hGmQzSzEOadJ");
    curl_easy_setopt(hnd, CURLOPT_HTTPHEADER, headers);
    
    curl_easy_setopt(hnd, CURLOPT_POSTFIELDS, "code=4%2FYxFunij3D3aBdBolu0wDJvM1heM17gfg5e-gYjby2cU&client_id=982555336638-e1e18fh47oo0dceecq9v1pejm4p7ske8.apps.googleusercontent.com&client_secret=2RpCEltwtZvkUS4MsX6rzwmG&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&grant_type=authorization_code");
    
    CURLcode ret = curl_easy_perform(hnd);
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    至此,我們就可以在分享給用戶的地址中觀看到直播視頻了。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章