将视频添加到 YouTube 上用户的“稍后观看”播放列表

Posted

技术标签:

【中文标题】将视频添加到 YouTube 上用户的“稍后观看”播放列表【英文标题】:Add video to user's "Watch Later" playlist on YouTube 【发布时间】:2017-07-19 16:40:37 【问题描述】:

目的是使用 YouTube API 创建一个稍后观看按钮。当用户单击按钮时,视频将保存到用户的“稍后观看”播放列表中。类似于在您自己的网站上实现 Facebook 赞按钮时的工作方式。

到目前为止,我们在 API 文档中有两个官方条目:

Retrieving and updating a users playlist。 Adding video to playlist:描述了一种形成 XML 文本格式的方法,该格式自动将视频添加到“稍后观看”播放列表中。

我们在 API 文档中有许多 php code samples。

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

【问题讨论】:

考虑到这个问题的复杂性,我会在两天内给这个问题至少100分的赏金。 到目前为止您尝试过什么?你在哪里出错了? 【参考方案1】:

正在检索“稍后观看”播放列表:

正如其他人指出的那样,YouTube 不再允许这样做

将视频添加到同一个列表中非常简单:

curl --request POST \
  'https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&key=[YOUR_API_KEY]' \
  --header 'Authorization: Bearer [YOUR_ACCESS_TOKEN]' \
  --header 'Accept: application/json' \
  --header 'Content-Type: application/json' \
  --data '"snippet":"playlistId":"WL","position":0,"resourceId":"kind":"youtube#video","videoId":"M7FIvfx5J10"' \
  --compressed

您可以在此处找到 Javascript 代码 sn-p 等:https://developers.google.com/youtube/v3/docs/playlistItems/insert

【讨论】:

【参考方案2】:

稍后观看播放列表是 ID 为 WL 的播放列表。您可以像添加其他 Youtube 播放列表一样向该播放列表添加视频。

您首先需要转到您的Google developer console:

为您的项目启用 Youtube 数据 API 生成Oauth Client ID

然后您可以使用下面的代码进行身份验证,检索具有https://www.googleapis.com/auth/youtube 范围的访问令牌,然后将视频添加到您稍后观看的播放列表中。

对于以下 Javascript 和 PHP 示例,当按下按钮时,如果尚未经过身份验证,它会登录用户并将视频添加到经过身份验证的用户的稍后观看播放列表中。


Javascript

这是基于 Google here 提供的 api-samples。

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

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

index.html

<!doctype html>
<html>

<head>
    <title>Add to Watch Later playlist</title>
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
    <style>
    .btn-tech 
        color: #2c3e50;
        border: solid 2px #2c3e50;
        background: transparent;
        transition: all 0.3s ease-in-out;
        margin: 20px;
        border-radius: 20% 20% 20% 20%;
    

    .btn-tech:hover,
    .btn-tech:active,
    .btn-tech.active 
        color: #FFFFFF;
        background: #2c3e50;
        cursor: pointer;
    
    </style>
</head>

<body>
    <div id="watch_later">
        <div id="buttons">
            <label>Enter Video ID you want to add to Watch Later playlist :
                <input id="video-id" value='T4ZE2KtoFzs' type="text" />
            </label>
        </div>
        <div class="like">
            <a id="fb-link">
                <span class="btn-tech fa-stack fa-3x">
                  <i class="fa fa-thumbs-up fa-stack-1x"></i>
                </span>
            </a>
        </div>
        <div id="playlist-container">
            <span id="status"></span>
        </div>
        <p>
            <a href="https://www.youtube.com/playlist?list=WL">check your watch later playlist</a>
        </p>
    </div>
    <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;
    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) 

        $('.like').off('click');
        $('.like').click(function(e) 
            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.
            $('.pre-auth').hide();
            $('.post-auth').show();
            loadAPIClientInterfaces();

            $('#add_to_wl').click(function(e) 
                addVideoToPlaylist();
            );
        
    

    function loadAPIClientInterfaces() 
        gapi.client.load('youtube', 'v3', function() 
            if (init) 
                init = false;
                addVideoToPlaylist();
            
        );
    
    // Add a video ID specified in the form to the playlist.
    function addVideoToPlaylist() 
        addToPlaylist($('#video-id').val());
    
    // 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) 
                $('#status').html('<pre>Succesfully added the video : ' + JSON.stringify(response.result) + '</pre>');
             else if (response.code == 409) 
                $('#status').html('<p>Conflict : this video is already on your Watch Later playlist</p>');
             else if (response.code == 404) 
                $('#status').html('<p>Not Found : this video hasnt been found</p>');
             else 
                $('#status').html('<p>Error : code ' + response.code + '</p>');
            
        );
    
    </script>
    <script src="https://apis.google.com/js/client.js?onload=googleApiClientReady"></script>
</body>

</html>

用您自己的客户 ID 替换 OAUTH2_CLIENT_ID

在 API 响应中,我检查以下状态代码:

409 : 该视频已在播放列表中 404 : 找不到视频

PHP

基于google-api php sample:

安装作曲家:见instructions

安装 google-api 客户端:

composer require google/apiclient:~2.0

php脚本watchlater.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($videoId) && !isset($_GET['state'])) 

      file_put_contents('php://stderr', print_r("adding video to watch later playlist " . $videoId . "\n", TRUE));

      $playlistId = "WL";
      // 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);

      $_SESSION['video'] = "";
  
  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'];

    // 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 Watch Later playlist</title>
    <link href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
    <style>
    .btn-tech 
        color: #2c3e50;
        border: solid 2px #2c3e50;
        background: transparent;
        transition: all 0.3s ease-in-out;
        margin: 20px;
        border-radius: 20% 20% 20% 20%;
    

    .btn-tech:hover,
    .btn-tech:active,
    .btn-tech.active 
        color: #FFFFFF;
        background: #2c3e50;
        cursor: pointer;
    
    </style>
</head>
<body>
   <div id="watch_later">
        <form id="form" action="watchlater.php"">

          <label>Enter Video ID you want to add to Watch Later playlist :
                <input id="video-id" name="video" value='T4ZE2KtoFzs' type="text" />
          </label>

          <div>
              <span class="btn-tech fa-stack fa-3x" onclick="javascript:document.getElementById('form').submit();">
                <i class="fa fa-thumbs-up fa-stack-1x"></i>
              </span>
          </div>
        </form>
        <div id="playlist-container">
          <?php echo $response ?>
        </div>
        <p>
            <a href="https://www.youtube.com/playlist?list=WL">check your watch later playlist</a>
        </p>
    </div>
</body>
</html>

$OAUTH2_CLIENT_ID$OAUTH2_CLIENT_SECRET 替换为它们各自的值。另外,你必须在谷歌控制台设置一个redirect_uri,这里是http://localhost/watchlater.php

在PHP版本中,您可以看到我将视频ID存储在$_SESSION["video"]中,以便在google身份验证重定向到watchlater.php时能够立即添加它


这是该项目的 google 控制台Oauth Client ID 屏幕(适用于上述 Javascript 和 PHP 版本):

请注意:

对于 Javascript 版本:您需要 CLIENT_ID 并设置 Javascript Origin 对于PHP版本:你需要CLIENT_IDCLIENT_SECRET,设置Javascript Origin并设置重定向URI

测试注意,我注意到如果您想重新添加视频,手动删除视频可能需要一些时间

【讨论】:

非常感谢您的回复。我们说话的时候,我正在 jsbin 上对此进行测试。有什么方法可以使用单个按钮(类似于 Facebook Like 按钮)的示例来更新此答案,当您单击它时,它会将特定的 YouTube 视频添加到“稍后观看”播放列表中。如果用户已注销,则它会加载一个弹出窗口以允许用户登录;然后将其添加到他们的播放列表中。到目前为止,我的问题是流畅地进行登录过程。 我已经根据您的要求更新了我的帖子,请查看现场演示 here。请注意,当用户第一次登录时,输入文本中的videoId会在之后添加到播放列表中,然后可以添加更多视频而无需登录弹出窗口 Authorized redirect URIs 不需要,因为您不想在身份验证成功时将用户重定向到另一个页面。您必须使用基本 URI 指定一个 Authorized JavaScript origins,在我的情况下,https://bertrandmartel.github.io 是 this demo。对于上面的小提琴链接,您可以使用https://fiddle.jshell.net 啊,你知道了,我的朋友。再次感谢您抽出宝贵时间发布这个非常完整的答案。 您可以将单击按钮的引用存储为全局变量或将其传递给您的回调函数。 Here 是一个全局变量的解决方案【参考方案3】:

我不知道这是否会对您有很大帮助,因为我从未使用过 Youtube 的 API。但是请查看this 回答,了解如何使用 Youtube 的 API v3 获取稍后观看的播放列表。

然后您可以查看来自 Youtube 文档的 this,用于将元素插入给定的播放列表。

无论如何我不确定这是否可行(你可以试一试),因为September 15, 2016 revision:

参考列表中的第2.2点:

频道资源的 contentDetails.relatedPlaylists.watchHistory 和 contentDetails.relatedPlaylists.watchLater 属性现在分别包含所有频道的 HL 和 WL 值。

需要明确的是,这些属性仅对检索有关用户自己频道的数据的授权用户可见。属性始终包含值 HL 和 WL,即使对于检索有关用户自己的频道的数据的授权用户也是如此。因此,无法通过 API 检索观看历史记录和稍后观看的播放列表 ID。

此外,为频道的观看历史记录或稍后观看的播放列表检索播放列表详细信息 (playlists.list) 或播放列表项 (playlistItems.list) 的请求现在返回空列表。此行为适用于新值 HL 和 WL,以及您的 API 客户端可能已存储的任何观看历史记录或稍后观看的播放列表 ID。

【讨论】:

以上是关于将视频添加到 YouTube 上用户的“稍后观看”播放列表的主要内容,如果未能解决你的问题,请参考以下文章

无法将视频插入稍后观看 (WL) 播放列表

在Google网站上自行使用Google API(例如在youtube.com上)

将视频添加到 YouTube 上用户的收藏夹/点赞播放列表

Youtube API 获取稍后观看播放列表

Youtube Data API v3 PlaylistItems 更新不适用于“稍后观看”播放列表

YouTube 嵌入 showinfo 已被弃用