Google 脚本:使用 Youtube API 的 Urlfetchapp 在共享云端硬盘文件夹中上传不同所有者的视频时遇到问题。处理放弃

问题描述 投票:0回答:3

我目前正在尝试使用此 SO 帖子中的以下代码自动将视频从共享驱动器文件夹上传到 Youtube:

function upload() { var driveurl = `https://drive.google.com/file/d/AAAAAAAAAAAAAAAAAAAAAAAAA/view?usp=share_link` var match = driveurl.match(/([a-z0-9_-]{25,})[$/&?]/i).pop(); var url = `https://www.googleapis.com/drive/v3/files/`+match+`?alt=media`; var title = "title"; var description = "test"; var topics = "TEST"; var blob,mp4_fileId,part,requestResource,response; var options = {},snippet = {}; /* You will need to create a GCP standard project and associate it with this Apps Script project- In the new code editor click the settings cog wheel and scroll down to: Google Cloud Platform (GCP) Project - You may get an error: In order to change your project, you will need to configure the OAuth consent screen. Configure your OAuth Consent details. And if you do not have a Google Workspace account then you wont be able to set up the GCP project as "INTERNAL" You will need to enable the Google Drive API and the YouTube API in the associated GCP project - */ /* This code needs the file ID of the MP4 file in your Google Drive - To get the file ID of an MP4 video file in Google Drive, right click the MP4 in your Google Drive and choose, "Get link" The link will look like this: https://drive.google.com/file/d/FILE_ID_IS_HERE/view?usp=sharing In the URL is the file ID */ options = { "method" : "get", "headers" : {"Authorization": "Bearer " + ScriptApp.getOAuthToken()}, "muteHttpExceptions":true } var video = UrlFetchApp.fetch(url,options); response = YouTube.Videos.insert({ snippet:{ title: title, description: description, tags: topics }, status:{ privacyStatus: "public", }, }, "snippet,status", video ); Logger.log(JSON.stringify(response)); Logger.log(response.id) }
当我是文件的所有者时,代码运行得很好。但是,当我尝试从同一文件夹中的另一个用户获取文件时,代码不再起作用。它尝试将视频推送到 YouTube,但导致我的 YouTube 频道中出现错误“正在处理放弃”。如果我复制文件并成为副本的所有者,它就可以正常工作,因此对于特定视频来说并不是什么特别的事情。

我想尝试一些

像这样的函数Drive.File.get(ID)不会产生正确的对象类型,即它需要是一个blob,但我不知道如何将它到达那里。 DriveApp.getFileById(match).getBlob() 是我的想法,但由于今天达到了 YouTube 的上传限制,我必须等到明天才能测试,而且我对提供的链接并不乐观。

似乎存在一些与权限相关的错误,但我不完全确定如何继续修复它。任何想法将不胜感激。

google-apps-script google-drive-api youtube-api
3个回答
0
投票
我相信您的目标如下。

从您的以下回复来看,

我们的文件不大于 100MB。所以

<100MB for the file size.

我了解到您要上传的文件大小小于100 MB。

在这种情况下,需要使用断点续传的方式上传到YouTube。在这种情况下,我已经将其发布在我的博客上。

参考作者:我 但是,当我在 Stackoverflow 中搜索时,我找不到它。所以,在这里,我想将其作为答案发布。

示例脚本。

此示例脚本使用 Drive API 和 YouTube API。因此,

请在高级 Google 服务中启用它们。并且,请将以下示例脚本复制并粘贴到 Google Apps 脚本的脚本编辑器中。

在您问题的显示脚本中,我认为

match

 是文件 ID。

function myFunction() { // Please set the file ID of video file and the metadata for uploading it to YouTube. const fileId = "###"; const metadata = { snippet: { description: "Upload sample.", title: "Sample uploaded video." }, status: { privacyStatus: "private" }, }; // 1. Retrieve location. const headers = { authorization: "Bearer " + ScriptApp.getOAuthToken() }; const url1 = encodeURI( "https://www.googleapis.com/upload/youtube/v3/videos?uploadType=resumable&part=snippet,status" ); const res1 = UrlFetchApp.fetch(url1, { headers, payload: JSON.stringify(metadata), contentType: "application/json", muteHttpExceptions: true, }); if (res1.getResponseCode() != 200) { console.log(res1.getContentText()); return; } const location = res1.getAllHeaders()["Location"]; console.log("Got Location."); // 2. Calculate chunks. const chunkSize = 20971520; // 20 MB const { fileSize } = Drive.Files.get(fileId, { supportsAllDrives: true, fields: "fileSize", }); const chunks = [...Array(Math.ceil(fileSize / chunkSize))].map((_, i, a) => [ i * chunkSize, i == a.length - 1 ? fileSize - 1 : (i + 1) * chunkSize - 1, ]); console.log("Calculated chunk data."); // 3. Retrieve chunks from Google Drive with the partial download and uploading chunks to YouTube with the resumable upload. const url2 = `https://www.googleapis.com/drive/v3/files/${fileId}?alt=media&supportsAllDrives=true`; let res2; const len = chunks.length; let responseObject; chunks.forEach((e, i) => { console.log(`Now... ${i + 1}/${len}`); const params2 = { headers: { authorization: headers.authorization, range: `bytes=${e[0]}-${e[1]}`, }, }; res2 = UrlFetchApp.fetch(url2, params2).getContent(); const params3 = { headers: { "Content-Range": `bytes ${e[0]}-${e[1]}/${fileSize}` }, payload: res2, muteHttpExceptions: true, }; console.log("Downloaded a chunk, and upload a chunk."); const res3 = UrlFetchApp.fetch(location, params3); const statusCode = res3.getResponseCode(); if (statusCode == 200) { console.log("Done."); // console.log(res3.getContentText()); responseObject = JSON.parse(res3.getContentText()); } else if (statusCode == 308) { console.log("Upload the next chunk."); res2.splice(0, res2.length); } else { throw new Error(res3.getContentText()); } }); // console.log(responseObject); // Here, you can retrieve the response object. console.log(responseObject.id); // Here, you can retrieve the video ID. // Please don't remove the following comment line. This comment line is important for running this script. // YouTube.Videos.insert(); // This is used for automatically detecting the scope of "https://www.googleapis.com/auth/youtube" with the script editor. }
测试:

当该脚本运行时,您可以在日志中看到以下进程。

Got Location. Calculated chunk data. Now... 1/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 2/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 3/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 4/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 5/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 6/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 7/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 8/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 9/10 Downloaded a chunk, and upload a chunk. Upload the next chunk. Now... 10/10 Downloaded a chunk, and upload a chunk. Done. { "kind": "youtube#video", "etag": "###", "id": "###", "snippet": {,,,}, "status": {,,,} }
重要

    在此示例脚本中,块大小为 20 MB 作为示例。您可以修改这个。但是,当这个尺寸很大时,可能会出现错误。请注意这一点。
  • 如果您没有YouTube频道,则无法上传视频文件。
  • 当您的账户未经谷歌方面确认时,超过15分钟的视频数据无法上传。请注意这一点。
  • 现阶段,Google Apps 脚本的最长执行时间为 6 分钟。因此,当您要上传较大的视频数据时,由于最大执行时间的原因,数据可能无法完全上传。请注意这一点。
    • 如果你想上传更大尺寸的视频数据,我认为你可以通过执行带有时间驱动触发器的脚本来实现。但是,在这种情况下,需要修改上面的脚本。请注意这一点。在这篇文章中,介绍了简单的示例脚本。
    • 我确认当我测试100MB时,没有出现错误。所以,关于你的情况,我认为这个脚本可以使用。
参考文献

  • Curl 命令使用 YouTube API 将视频文件上传到 YouTube,并可断点续传
  • 可断点上传

0
投票
更改代码:

var video = UrlFetchApp.fetch(url,options);

到:
var video = DriveApp.getFileById(match).getBlob()
彻底解决问题。不过,我了解到使用此过程有 50MB 的文件大小上传限制,这对于视频来说似乎很小。但是,如果有人尝试将任何小于该尺寸的视频上传到他们的频道。我清理了代码,效果很好

function upload4() { var driveurl = `https://drive.google.com/file/d/AAAAAAAAAAAAAAAAAAAAAAAAA?usp=share_link` var match = driveurl.match(/([a-z0-9_-]{25,})[$/&?]/i).pop(); var title = "title"; var description = "test"; var topics = "TEST"; var video = DriveApp.getFileById(match).getBlob(); var response = YouTube.Videos.insert({ snippet:{ title: title, description: description, tags: topics }, status:{ privacyStatus: "private", }, }, "snippet,status", video ); Logger.log(JSON.stringify(response)); Logger.log(response.id) }
    

0
投票
@Andrewncf @Tanaike

Tanaike 解决方案看起来不错,但不起作用。只有“未经授权”的结果。我连接了所有的 gcp、图书馆、誓言等等。怎么解决?

顺便问一下,这个脚本可以与具有多个 YouTube 频道的 Google 帐户一起使用吗?如何从所有频道中选择一个?

© www.soinside.com 2019 - 2024. All rights reserved.