YouTube API v3 over HTTP POST:上传视频时无法设置片段(标题最终为“未知”)

Posted

技术标签:

【中文标题】YouTube API v3 over HTTP POST:上传视频时无法设置片段(标题最终为“未知”)【英文标题】:YouTube API v3 over HTTP POST: can't set snippet while uploading a video (title ends up as "unknown") 【发布时间】:2014-10-25 02:20:51 【问题描述】:

我正在尝试允许用户从我的网站上传 YouTube 视频,但我没有使用 javascript API,因为用户需要能够将内容上传到我的频道,而不是使用他们自己的帐户,而我不能弄清楚如何使用 JS API 做到这一点。

无论如何,最终结果是我有一个 html 元素发布视频。视频被上传,但标题为“未知”且没有描述等。不知道我做错了什么。这是发送到 https://www.googleapis.com/upload/youtube/v3/videos?part=snippet,status&access_token=[accesstoken] 的 HTTP POST(如 multipart/form-data)的有效负载:

------WebKitFormBoundaryqKACn63lpjqwi0sA
Content-Disposition: form-data; name="status[privacyStatus]"

unlisted
------WebKitFormBoundaryqKACn63lpjqwi0sA
Content-Disposition: form-data; name="snippet[title]"

Test Video Title
------WebKitFormBoundaryqKACn63lpjqwi0sA
Content-Disposition: form-data; name="snippet[description]"

Test video description
------WebKitFormBoundaryqKACn63lpjqwi0sA
Content-Disposition: form-data; name="videoFile"; filename="test_vide_upload.mp4"
Content-Type: video/mp4


------WebKitFormBoundaryqKACn63lpjqwi0sA--

我假设snippetstatus 字段的表单名称是错误的,但我尝试了各种选项,但无法正常工作。我还尝试发送带有 JSON 编码值 "snippet":"description":"Test video description","title":"Test Video Title","status":"privacyStatus":"unlisted" 的单个表单字段 data,但这也不起作用。

我总是从 API 获得成功的 JSON 响应,带有 sn-p 和状态,并且视频已上传,但尚未设置 sn-p 和状态,它们是空值或默认值。有什么线索吗?

【问题讨论】:

你有没有想过这个问题?我遇到了完全相同的问题.. 总是成功上传,但从不设置 sn-p 信息。 @user3344977 我最终确实弄清楚了。只需挖掘代码并将其发布为答案:***.com/a/36213106/458614 查看 Google 的客户端 API 库代码,似乎应该可以在一个请求中完成所有操作。应该有两部分,第一部分是 JSON。我没有为 Youtube 找到相同的规范,但 Drive API 文档中给出的多部分规范很可能也适用于 Youtube:developers.google.com/drive/api/v3/multipart-upload。不过这是否值得有些疑问,因为它看起来比仅仅发出两个单独的请求要复杂得多。 【参考方案1】:

如果您想在单个 POST 中发送它,您需要在 JSON blob 对象(例如通过 JSON.stringify)中发送元数据(即 sn-p 和状态数组),基本上作为第二个文件上传。您可能还应该在标头中设置访问令牌(很惊讶它在 URL 中工作):

headers: Authorization: 'Bearer ' + [accesstoken]

这里有一个很好的 JS/CORS 示例:

https://code.google.com/p/youtube-api-samples/source/browse/yt-upload-javascript/index.js

你可以去掉

window.oauth2Callback = function(authResult) ...

有点,因为您已经拥有所需的访问令牌,否则它应该对您有用(我有一个概念证明做完全相同的事情,从这段代码中大量借用)。

这里也有一些有用/相关的内容:

http://lithostech.com/2013/10/upload-google-youtube-api-v3-cors/

Steve 似乎通过检查 ruby​​ 客户端库的输出发现了将元数据作为二进制对象发布的必要性。根据这个***帖子:

Upload video on Youtube using curl and api v3

同样的事情可以通过两个帖子完成(参见 Chad Befus 的回答),第一个包含元数据,第二个包含视频文件。我没有这种方法的经验。

【讨论】:

【参考方案2】:

我最终只能通过调用 2 个 API 来完成这项工作 - 一个用于上传视频(作为 multipart/form-data POST)并获取结果 ID,第二个通过该 ID 更新视频(作为 application/json PUT 与 snippet 在正文中)。

我从一个这样的 HTML 表单开始:

<form id="upload-yt-video" action="https://www.googleapis.com/upload/youtube/v3/videos?part=snippet&access_token=YOUR_TOKEN_HERE" method="post" enctype="multipart/form-data">
    <input type="text" name="title" placeholder="Video title">
    <textarea name="description" placeholder="Video description"></textarea>
    <input type="file" accept="video/*" name="videoFile">
    <input type="submit" value="Upload Video">
</form>

该表单自己上传视频,然后在JS中你可以捕获表单提交结果来获取视频ID,然后在纯JS中进行第二次AJAX调用来更新它:

var YOUTUBE_API_TOKEN = 'YOUR_TOKEN_HERE';
var YOUTUBE_VID_CATEGORY_ID = 24; // "entertainment" as an example - note that a category ID is required
var YOUTUBE_VID_PRIVACY_STATUS = 'unlisted';

$('#upload-yt-video').ajaxForm(
  success: function(res, status)  
    if (status !== 'success' || ! res.id) 
      console.error('problem uploading the video, response status:', status, 'response:', res);
      return;
    

    console.log('form submission successful, video uploaded to youtube! response:', res);

    updateYouTubeVideo(
      id: res.id,
      token: YOUTUBE_API_TOKEN,
      title: $('#upload-yt-video [name=title]').val(),
      description: $('#upload-yt-video [name=description]').val()
    , function(err, res) 
      if (err) 
        console.error('problem uploading the video - error while updating video attributes after upload:', err);
      
      else 
        console.log('video updated! upload complete. response:', res);
      
    );
  ,
  error: function() 
    console.error('form submission failed', arguments);
  
);

function updateYouTubeVideo(args, cb) 
  if (!args || !args.id || !args.token) 
    console.error('missing args: must at least include id and token');
    return;
  

  var apiArgs = 
    id: args.id,
    snippet: 
      description: args.description || '',
      title: args.title || 'Video ' + new Date().toDateString(),
      categoryId: YOUTUBE_VID_CATEGORY_ID
    ,
    status: 
      privacyStatus: YOUTUBE_VID_PRIVACY_STATUS
    
  ;

  $.ajax(
    type: 'PUT',
    url: 'https://www.googleapis.com/youtube/v3/videos?part=snippet,status',
    contentType: 'application/json',
    headers: 
        Authorization: 'Bearer ' + args.token
    ,
    data: JSON.stringify(apiArgs),
    dataType: 'text',
    success: function(data) 
      if ($.type(data) === "string") data = JSON.parse(data);
      cb(null, data);
    ,
    error: function(request, err)
      cb(err);
    
  );

注意 #1 - 这使用 this jQuery plugin 来捕获初始表单提交。免责声明 #1 - 我从一个代码库中改编了这个我没有寿命更长,因此我无法对其进行测试,因此此处可能存在轻微的拼写错误或错误。免责声明 #2 - 这在 2014 年 9 月有效 - 可能已经更新从那时起的 API!

【讨论】:

以上是关于YouTube API v3 over HTTP POST:上传视频时无法设置片段(标题最终为“未知”)的主要内容,如果未能解决你的问题,请参考以下文章

使用新 API v3 获取 youtube 视频信息

youtube api v3 - 多个搜索作者 + 关键字

无帐号的 Youtube 视频列表(使用新的 API v3)

YouTube API v3 响应缺少视频

如何在 YouTube API v3 上检索“频道中的频道”

如何使用 JavaScript API V3 以 JSON 格式获取 youtube 播放列表的数据