【问题标题】:Add video to user's Favorite/Like playlist on YouTube将视频添加到 YouTube 上用户的收藏夹/点赞播放列表
【发布时间】:2017-08-30 23:00:16
【问题描述】:

目的是使用 YouTube API 创建一个收藏/点赞按钮。当用户点击该按钮时,视频被保存到用户的收藏夹/点赞播放列表中。

就像您在自己的网站上实现 Facebook 点赞按钮时的工作原理一样。

这本质上是Bertrand Martel 在我之前的question 上发布的出色解决方案的后续问题,我们旨在将视频添加到“稍后观看”播放列表中。

这个特定功能的工作代码是:

<!-- button 1 -->
<button type="submit" data-youtube-video-id="EH3gqI2NAiE" value="Watch Later" class="ma_youtube_watch_later" name="send">
  <div class="ma_youtube_watch_later_text">Watch Later</div>
</button>

<!-- button 2 -->
<button type="submit" data-youtube-video-id="0EMmKIIF-zE" value="Watch Later" class="ma_youtube_watch_later" name="send">
  <div class="ma_youtube_watch_later_text">Watch Later</div>
</button>

<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
<script>
  // By Bertrand Martel: https://stackoverflow.com/a/42561941/1649673
  var OAUTH2_CLIENT_ID = '28993181493-c9o6hdll3di0ssvebfd4atf13edqfu9g.apps.googleusercontent.com';
  var OAUTH2_SCOPES = [
    'https://www.googleapis.com/auth/youtube'
  ];
  var init = false;
  var youtube_video_id = '';

  var button = null;

  googleApiClientReady = function() {
    gapi.auth.init(function() {
      window.setTimeout(checkAuth, 1);
    });
  }

  function checkAuth() {
    gapi.auth.authorize({
      client_id: OAUTH2_CLIENT_ID,
      scope: OAUTH2_SCOPES,
      immediate: true
    }, handleAuthResult);
  }
  // Handle the result of a gapi.auth.authorize() call.
  function handleAuthResult(authResult) {

    jQuery('.ma_youtube_watch_later').off('click');
    jQuery('.ma_youtube_watch_later').click(function(e) {

      button = this;

      var youtube_video_id = jQuery(this).attr("data-youtube-video-id");

      // Add a video ID specified in the form to the playlist.
      function addVideoToPlaylist() {
        //addToPlaylist(jQuery('#video-id').val());
        addToPlaylist(youtube_video_id);
      }

      if (authResult && !authResult.error) {
        addVideoToPlaylist();
      } else {
        init = true;
        gapi.auth.authorize({
          client_id: OAUTH2_CLIENT_ID,
          scope: OAUTH2_SCOPES,
          immediate: false
        }, handleAuthResult);
      }
      return false;
    });

    if (authResult && !authResult.error) {
      // Authorization was successful. Hide authorization prompts and show
      // content that should be visible after authorization succeeds.
      jQuery('.pre-auth').hide();
      jQuery('.post-auth').show();
      loadAPIClientInterfaces();

      jQuery('#add_to_wl').click(function(e) {

        button = this;

        addVideoToPlaylist(self);
      });
    }
  }

  function loadAPIClientInterfaces() {
    gapi.client.load('youtube', 'v3', function() {
      if (init) {
        init = false;
        addVideoToPlaylist();
      }
    });
  }

  // Add a video to a playlist. The "startPos" and "endPos" values let you
  // start and stop the video at specific times when the video is played as
  // part of the playlist. However, these values are not set in this example.
  function addToPlaylist(id, startPos, endPos) {
    var details = {
      videoId: id,
      kind: 'youtube#video'
    }
    if (startPos != undefined) {
      details['startAt'] = startPos;
    }
    if (endPos != undefined) {
      details['endAt'] = endPos;
    }
    var request = gapi.client.youtube.playlistItems.insert({
      part: 'snippet',
      resource: {
        snippet: {
          playlistId: "WL",
          resourceId: details
        }
      }
    });

    request.execute(function(response) {
      console.log(response);
      if (!response.code) {
        //jQuery('#status').html('<pre>Succesfully added the video : ' + JSON.stringify(response.result) + '</pre>');

        // change button text
        $(button).text('Video added');

      } else if (response.code == 409) {

        //jQuery('#status').html('<p>Conflict : this video is already on your Watch Later playlist</p>');

        // change button text
        $(button).text('Already added');

      } else if (response.code == 404) {
        //jQuery('#status').html('<p>Not Found : this video hasnt been found</p>');

        // change button text
        $(button).text('Video not found');

      } else {
        //jQuery('#status').html('<p>Error : code ' + response.code + '</p>');

        // change button text
        $(button).text('Error: Try again');

      }
    });
  }

</script>
<script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>

我们在 API 文档中有许多 PHP code samples。我们还有一些关于adding a video to playlist 的文档。

如何使用 PHP 或/和 javascript 来实现?

【问题讨论】:

    标签: javascript php video youtube youtube-api


    【解决方案1】:

    您可以使用以下参数找到带有频道列表端点的 Like & Favorite 播放列表 ID(检查 this sample request):

    {
        mine: true,
        part: 'contentDetails'
    }
    

    您将获得relatedPlaylists 中的播放列表列表,包括likesfavoritesuploadswatch laterwatch history

    {
        "kind": "youtube#channelListResponse",
        "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/S1x68O9aSpvmndklrnSwKw_yYdE\"",
        "pageInfo": {
            "totalResults": 1,
            "resultsPerPage": 1
        },
        "items": [{
            "kind": "youtube#channel",
            "etag": "\"m2yskBQFythfE4irbTIeOgYYfBU/ura_vsrPt5tCZkjjGbH3ihN3Bq4\"",
            "id": "UCnQt5EmYRfX1uVYtwPNj7Dg",
            "contentDetails": {
                "relatedPlaylists": {
                    "likes": "LLnQt5EmYRfX1uVYtwPNj7Dg",
                    "favorites": "FLnQt5EmYRfX1uVYtwPNj7Dg",
                    "uploads": "UUnQt5EmYRfX1uVYtwPNj7Dg",
                    "watchHistory": "HL",
                    "watchLater": "WL"
                }
            }
        }]
    }
    

    对于 WatchLater 和 WatchHistory,所有用户(分别为 WL 和 HL)的 playlistId 相同

    您可以在 JavaScript 中使用 gapi.client.youtube.channels.list 调用频道列表端点,就像调用播放列表插入 API 一样。

    然后,您可以使用 playlistId 将您的视频插入到另一个播放列表中,而不是稍后观看。

    在以下代码中,您将找到 3 个按钮,用于将不同的视频添加到 Watch Later 播放列表、Like 播放列表和 Favorite 播放列表


    Javascript

    Here 是带有source code 的现场演示(如下)

    Here 是一个小提琴。替换您的客户端 ID 并在开发者控制台中添加为授权的 JavaScript 来源:https://fiddle.jshell.net

    <!doctype html>
    <html>
    
    <head>
        <title>Add to multiple playlists</title>
    </head>
    
    <body>
        <input type="submit" data-youtube-video-id="EH3gqI2NAiE" data-type="WL" value="Add to Watch Later playlist" class="yt_add_to_playlist" />
        <input type="submit" data-youtube-video-id="0EMmKIIF-z" data-type="likes" value="Add to Like playlist" class="yt_add_to_playlist" />
        <input type="submit" data-youtube-video-id="T4ZE2KtoFzs" data-type="favorites" value="Add to Favorite playlist" class="yt_add_to_playlist" />
        <script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
        <script>
        var OAUTH2_CLIENT_ID = '28993181493-c9o6hdll3di0ssvebfd4atf13edqfu9g.apps.googleusercontent.com';
        var OAUTH2_SCOPES = [
            'https://www.googleapis.com/auth/youtube'
        ];
        var init = false;
        var button = null;
    
        googleApiClientReady = function() {
            gapi.auth.init(function() {
                window.setTimeout(checkAuth, 1);
            });
        }
    
        function checkAuth() {
            gapi.auth.authorize({
                client_id: OAUTH2_CLIENT_ID,
                scope: OAUTH2_SCOPES,
                immediate: true
            }, handleAuthResult);
        }
    
        // Handle the result of a gapi.auth.authorize() call.
        function handleAuthResult(authResult) {
    
            jQuery('.yt_add_to_playlist').off('click');
            jQuery('.yt_add_to_playlist').click(function(e) {
    
                button = this;
    
                if (authResult && !authResult.error) {
                    addToPlaylist($(this).attr("data-youtube-video-id"), $(this).attr("data-type"));
                } else {
                    init = true;
                    gapi.auth.authorize({
                        client_id: OAUTH2_CLIENT_ID,
                        scope: OAUTH2_SCOPES,
                        immediate: false
                    }, handleAuthResult);
                }
                return false;
            });
    
            if (authResult && !authResult.error) {
                // Authorization was successful. Hide authorization prompts and show
                // content that should be visible after authorization succeeds.
                jQuery('.pre-auth').hide();
                jQuery('.post-auth').show();
                loadAPIClientInterfaces();
    
                jQuery('#add_to_wl').click(function(e) {
                    button = this;
                    addToPlaylist($(this).attr("data-youtube-video-id"), $(this).attr("data-type"));
                });
            }
        }
    
        function loadAPIClientInterfaces() {
            gapi.client.load('youtube', 'v3', function() {
                if (init) {
                    init = false;
                    addToPlaylist($(button).attr("data-youtube-video-id"), $(button).attr("data-type"));
                }
            });
        }
    
        function addToPlaylist(videoId, playlistType) {
    
            console.log("add to playlist type : " + playlistType);
    
            if (playlistType != "WL" && playlistType != "HL") {
    
                var request = gapi.client.youtube.channels.list({
                    mine: true,
                    part: 'contentDetails'
                });
    
                request.execute(function(response) {
                    var playlistId = response.result.items[0].contentDetails.relatedPlaylists[playlistType];
    
                    if (typeof playlistId != 'undefined') {
                        console.log("found playlist id : " + playlistId);
                        insertToPlaylist(videoId, playlistId);
                    } else {
                        console.log("playlist not found");
                    }
    
                });
    
            } else {
                insertToPlaylist(videoId, playlistType);
            }
        }
    
        function insertToPlaylist(videoId, playlistId) {
    
            var details = {
                videoId: videoId,
                kind: 'youtube#video'
            };
            var request = gapi.client.youtube.playlistItems.insert({
                part: 'snippet',
                resource: {
                    snippet: {
                        playlistId: playlistId,
                        resourceId: details
                    }
                }
            });
    
            request.execute(function(response) {
                console.log(response);
                if (!response.code) {
                    $(button).val('Video added');
                } else if (response.code == 409) {
                    $(button).val('Already added');
                } else if (response.code == 404) {
                    $(button).val('Video not found');
                } else {
                    $(button).val('Error: Try again');
                }
            });
        }
        </script>
        <script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
    </body>
    
    </html>
    

    用您自己的客户 ID 替换 OAUTH2_CLIENT_ID

    在 API 响应中,会检查状态代码以防找不到视频 (404)。如果视频已经在播放列表中,则返回409 状态代码,但仅用于稍后观看的播放列表(将现有视频添加到喜欢/收藏的播放列表不会改变任何内容)


    PHP

    和之前一样,基于google-api php sample

    • 安装作曲家:见instructions
    • 安装 google-api 客户端:

      composer require google/apiclient:~2.0
      

    php脚本multi-playlist.php

    <?php
    /**
     * Library Requirements
     *
     * 1. Install composer (https://getcomposer.org)
     * 2. On the command line, change to this directory (api-samples/php)
     * 3. Require the google/apiclient library
     *    $ composer require google/apiclient:~2.0
     */
    if (!file_exists(__DIR__ . '/vendor/autoload.php')) {
      throw new \Exception('please run "composer require google/apiclient:~2.0" in "' . __DIR__ .'"');
    }
    require_once __DIR__ . '/vendor/autoload.php';
    session_start();
    
    $response = "";
    
    /*
     * You can acquire an OAuth 2.0 client ID and client secret from the
     * {{ Google Cloud Console }} <{{ https://cloud.google.com/console }}>
     * For more information about using OAuth 2.0 to access Google APIs, please see:
     * <https://developers.google.com/youtube/v3/guides/authentication>
     * Please ensure that you have enabled the YouTube Data API for your project.
     */
    $OAUTH2_CLIENT_ID = 'YOUR_CLIENT_ID';
    $OAUTH2_CLIENT_SECRET = 'YOUR_CLIENT_SECRET';
    
    $client = new Google_Client();
    $client->setClientId($OAUTH2_CLIENT_ID);
    $client->setClientSecret($OAUTH2_CLIENT_SECRET);
    $client->setScopes('https://www.googleapis.com/auth/youtube');
    
    $redirect = filter_var('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['PHP_SELF'],
        FILTER_SANITIZE_URL);
    
    $client->setRedirectUri($redirect);
    // Define an object that will be used to make all API requests.
    $youtube = new Google_Service_YouTube($client);
    // Check if an auth token exists for the required scopes
    $tokenSessionKey = 'token-' . $client->prepareScopes();
    if (isset($_GET['code'])) {
      if (strval($_SESSION['state']) !== strval($_GET['state'])) {
        die('The session state did not match.');
      }
      $client->authenticate($_GET['code']);
      $_SESSION[$tokenSessionKey] = $client->getAccessToken();
      header('Location: ' . $redirect);
    }
    if (isset($_SESSION[$tokenSessionKey])) {
      $client->setAccessToken($_SESSION[$tokenSessionKey]);
    }
    // Check to ensure that the access token was successfully acquired.
    
    if ($client->getAccessToken()) {
      try {
    
        $videoId = "";
    
        if (isset($_GET['video'])){
          $videoId = $_GET['video'];
        }
        else if(isset($_SESSION['video'])){
          $videoId = $_SESSION['video'];
        }
    
        if (isset($_GET['action'])){
          $action = $_GET['action'];
        }
        else if(isset($_SESSION['action'])){
          $action = $_SESSION['action'];
        }
    
        if(isset($videoId) && isset($action) && !isset($_GET['state'])) {
    
          file_put_contents('php://stderr', print_r("adding video to watch later playlist " . $videoId . "\n", TRUE));
    
          if ($action == "Add to Watch Later playlist") {
            $playlistId = "WL";
          }
          else {
              $listResponse = $youtube->channels->listChannels("contentDetails", array(
                  'mine' => true
              ));
    
              if (!empty($listResponse)) {
                if ($action == "Add to Like playlist"){
                  $playlistId = $listResponse['items'][0]['contentDetails']['relatedPlaylists']['likes'];
                }
                else if ($action == "Add to Favorite playlist"){
                  $playlistId = $listResponse['items'][0]['contentDetails']['relatedPlaylists']['favorites'];
                }
              }
          }
    
          if (isset($playlistId)){
    
            // 5. Add a video to the playlist. First, define the resource being added
            // to the playlist by setting its video ID and kind.
            $resourceId = new Google_Service_YouTube_ResourceId();
            $resourceId->setVideoId($videoId);
            $resourceId->setKind('youtube#video');
    
            // Then define a snippet for the playlist item. Set the playlist item's
            // title if you want to display a different value than the title of the
            // video being added. Add the resource ID and the playlist ID retrieved
            // in step 4 to the snippet as well.
            $playlistItemSnippet = new Google_Service_YouTube_PlaylistItemSnippet();
            $playlistItemSnippet->setTitle('First video in the test playlist');
            $playlistItemSnippet->setPlaylistId($playlistId);
            $playlistItemSnippet->setResourceId($resourceId);
            // Finally, create a playlistItem resource and add the snippet to the
            // resource, then call the playlistItems.insert method to add the playlist
            // item.
            $playlistItem = new Google_Service_YouTube_PlaylistItem();
            $playlistItem->setSnippet($playlistItemSnippet);
    
            $playlistItemResponse = $youtube->playlistItems->insert(
                'snippet,contentDetails', $playlistItem, array());
    
            $response = json_encode($playlistItem);
          }
          else{
            $response = "no playlist selected";
          }
    
          $_SESSION['video'] = "";
          $_SESSION["action"] = "";
      }
      else{
        file_put_contents('php://stderr', print_r("no video was specified", TRUE));
      }
    
      } catch (Google_Service_Exception $e) {
        $response = htmlspecialchars($e->getMessage());
      } catch (Google_Exception $e) {
        $response = htmlspecialchars($e->getMessage());
      }
      $_SESSION[$tokenSessionKey] = $client->getAccessToken();
    } else {
    
      if(isset($_GET['video'])){
    
        $_SESSION["video"] = $_GET['video'];
        $_SESSION["action"] = $_GET['action'];
    
        // If the user hasn't authorized the app, initiate the OAuth flow
        $state = mt_rand();
        $client->setState($state);
        $_SESSION['state'] = $state;
        $authUrl = $client->createAuthUrl();
        header('Location: ' . $authUrl);
      }
    }
    ?>
    
    <!doctype html>
    <html>
    <head>
     <title>Add to playlists</title>
    </head>
    <body>
        <div>
            <form id="form" action="multi-playlist.php"">
                <input type="hidden"  name="video" value="EH3gqI2NAiE">
                <input name="action" type="submit" value="Add to Watch Later playlist" />
                <input name="action" type="submit" value="Add to Like playlist" />
                <input name="action" type="submit" value="Add to Favorite playlist" />
            </form>
            <div>
              <?php echo $response ?>
            </div>
        </div>
    </body>
    </html>
    

    对于这个 PHP 版本,请注意除了当前会话 $_SESSION["video"] 中的视频 id 之外,目标操作也存储在 $_SESSION["action"] 中,以便能够确定要使用哪个播放列表。使用$youtube-&gt;channels-&gt;listChannels 的频道列表端点检索播放列表。


    请注意,视频可能需要一些时间才能出现在播放列表中(有时需要几秒钟)

    【讨论】:

    • 感谢您花时间拼凑起来,谢谢。这周我要测试一下。我有一个问题。是否可以同时将视频添加到多个播放列表?例如,在类型数据属性值中,我们添加一个类似data-type="WL, likes" 的数组,并将视频添加到这些播放列表中。不确定 YouTube 是否有某种形式的屏蔽。
    • 我不这么认为,playlist insert endpoint 没有实现批量插入(playlistId 字段需要一个对象,使用数组时只考虑第一项) .您将需要进行 2 次连续的播放列表插入调用
    • 非常感谢您的解释。过去几天我一直处于非活动状态,未能按时奖励这笔赏金。我已通过this meta thread 与社区联系,希望能为您获得剩余积分!另外,我应该注意,我没有在我的本地环境中测试过这段代码(本周晚些时候会这样做),但从你之前的回答来看,它肯定会相应地发挥作用。
    • 别担心 :) 保持您的声誉,以备日后需要。如果您对此代码有任何问题,请告诉我
    • @BertrandMartel 您的代码中有错误。 else if (response.code == 409) 和其他仅适用于 WL 播放列表。它不适用于favoriteslikes 播放列表。因此,即使视频被添加到用户收藏的播放列表中,他们也会看到$(button).val('Video added');。您可以在自己的demo 中轻松看到此问题,只需单击两次喜欢或收藏一个...您有解决此问题的方法吗?除了这个问题,这个答案是一个怪物。恭喜你把它放在一起。如果可以的话 +1000!
    猜你喜欢
    • 2018-03-10
    • 2017-07-19
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    • 2015-12-31
    • 1970-01-01
    • 2023-03-24
    • 1970-01-01
    相关资源
    最近更新 更多