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

时间:2014-08-31 20:19:58

标签: http post youtube youtube-api

我正在尝试允许用户从我的网站上传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编码的值data发送单个表单字段{"snippet":{"description":"Test video description","title":"Test Video Title"},"status":{"privacyStatus":"unlisted"}},但这也不起作用。

我总是从API获得成功的JSON响应,包含代码段和状态,并且视频已上传,但片段和状态尚未设置,它们是空值或默认值。有线索吗?

2 个答案:

答案 0 :(得分:2)

如果要在单个POST中发送它,则需要在JSON blob对象(例如,通过JSON.stringify)中发送元数据(即片段和状态数组),基本上作为第二个文件上载。你可能也应该在标题中设置访问令牌(让它感到惊讶的是在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/

史蒂夫似乎已经通过检查ruby客户端库的输出来确定将元数据作为二进制对象发布的必要性。并根据这个stackoverflow帖子:

Upload video on Youtube using curl and api v3

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

答案 1 :(得分:1)

我最终只能通过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可能已有更新!