В настоящее время я пытаюсь автоматизировать загрузку видео из папки общего диска на Youtube, используя следующий код из этого поста SO:
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) не выдает правильный тип объекта, т.е. это должен быть большой двоичный объект, но я не могу понять, как его туда доставить. DriveApp.getFileById(match).getBlob() - это моя мысль, но мне нужно подождать до завтра, чтобы протестировать из-за того, что сегодня я достиг предела загрузки для YouTube, и я не оптимистичен в отношении предоставленной ссылки.
Кажется, есть какая-то ошибка, связанная с разрешениями, но я не совсем уверен, как ее исправить. Мы будем очень признательны за любые мысли.
@Tanaike извините за непонятный язык. Код больше не работает означает, что если файл принадлежит другому пользователю, YouTube выдает ошибку «Обработка брошена». Я успешно смог преодолеть это, заменив ``` var video = UrlFetchApp.fetch(url, options)``` на DriveApp.getFileById(match).getBlob()
. Я отвечу на свой вопрос, как только пройдет нужное время, чтобы SO разрешил мне. С другой стороны, теперь я узнал, что у YouTube.Videos.insert
есть ограничение на загрузку в 50 МБ, которое мне нужно выяснить, как обойти. Угу, но спасибо за комментарий
Спасибо за ответ. Могу я спросить вас о размере файла, который вы хотите загрузить?
Размер файла, по-видимому, имеет ограничение более 0,05 ГБ или 50 МБ для метода DriveApp.getFileById(match).getBlob()
. Метод video = UrlFetchApp.fetch(url,options)
не имеет этого ограничения. Я общался со службой поддержки GAS, и они указали на проблему, связанную с типом BLOB-объекта для объекта, и это вызывало ошибку размера файла. Не совсем уверен, как решить эту проблему, поскольку для Youtube.video.insert требуется тип большого двоичного объекта, если он загружается через Driveapp. И спасибо за ответ. Здесь всегда приятно общаться с людьми
Спасибо за ответ. Я должен извиниться за мое плохое знание английского языка. Про ограничение в 50 мб я так понял. Итак, я спросил ожидаемый размер файла, который вы хотите загрузить. Прошу прощения за это.
О, это моя вина, у нас есть файлы размером не более 100 МБ. Итак, <100 МБ для размера файла. Вот почему это расстраивает! Они едва превышают лимит!
Спасибо за ответ. Из вашего ответа я понял, что размер вашего файла меньше 100 МБ. Из этой ситуации я предложил ответ. Пожалуйста, подтвердите это.
Изменение кода:
var video = UrlFetchApp.fetch(url,options);
к:
var video = DriveApp.getFileById(match).getBlob()
решает проблему полностью. Однако я узнал, что при использовании этого процесса существует ограничение на загрузку файла размером 50 МБ, что кажется небольшим для видео. Однако, если кто-то пытается загрузить видео меньшего размера на свой канал. Я очистил код, и это работает хорошо
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)
}
Я считаю, что ваша цель заключается в следующем.
Из вашего следующего ответа,
у нас есть файлы размером не более 100 МБ. Итак, <100 МБ для размера файла.
Я понял, что размер файлов, которые вы хотите загрузить, меньше 100 МБ.
В этом случае требуется загрузить его на YouTube с возобновляемой загрузкой. В этом случае я уже разместил его в своем блоге. Ссылка Автор: я Но, когда я искал его в Stackoverflow, я не мог его найти. Итак, здесь я хотел бы опубликовать это как ответ.
В этом примере скрипта используются Drive API и YouTube API. Итак, включите их в расширенных сервисах Google. Скопируйте и вставьте следующий образец сценария в редактор сценариев Google Apps Script.
В вашем сценарии показа в вашем вопросе я думаю, что match
- это идентификатор файла.
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.info(res1.getContentText());
return;
}
const location = res1.getAllHeaders()["Location"];
console.info("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.info("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.info(`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.info("Downloaded a chunk, and upload a chunk.");
const res3 = UrlFetchApp.fetch(location, params3);
const statusCode = res3.getResponseCode();
if (statusCode == 200) {
console.info("Done.");
// console.info(res3.getContentText());
responseObject = JSON.parse(res3.getContentText());
} else if (statusCode == 308) {
console.info("Upload the next chunk.");
res2.splice(0, res2.length);
} else {
throw new Error(res3.getContentText());
}
});
// console.info(responseObject); // Here, you can retrieve the response object.
console.info(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": {,,,}
}
Это сработало потрясающе. Жаль, что я не нашел ваш пост в блоге, когда я работал над этим раньше. Спасибо за успешный ответ, он будет отмечен. Задам еще один вопрос. Мне интересно, можно ли вернуть id видео после завершения процесса? В исходном коде это было легко сделать с помощью var response = YouTube.Videos.insert
, за которым следовал response.id
, но в этом случае функция video.insert находится внутри комментария и больше не является объектом. Я вижу идентификатор в журнале выполнения, но не знаю, как его получить.
@Andrewncf Спасибо за ответ. Я рад, что ваша проблема была решена. Что касается вашего дополнительного вопроса I am wondering if it is possible to return the id of the video after the process is complete?
, я обновил свой ответ. Пожалуйста, подтвердите это.
Извините за задержку с принятием ответа, я исчерпал свою квоту API Youtube и не мог протестировать до сих пор. Для приложения, которое я использую, [требуется оператор возврата] (support.google.com/appsheet/answer/12309564?hl=en). Я пытался использовать простое return console.info(responseObject.id);
, но не повезло. То же самое с var outputID = console.info(responseObject.id); return outputID
Есть мысли? Прошу прощения, так как я привык к более декларативным форматам, поэтому я не уверен, что есть лучший способ? В любом случае, спасибо за первоначальную помощь. Это было потрясающе!!!!!!
@Andrewncf Спасибо за ответ. Я рад, что ваша проблема была решена. Насчет I tried to simple use return console.info(responseObject.id); but no luck there.
, к сожалению, когда я тестировал свой скрипт, метаданные загруженного видео и идентификатор видео можно увидеть в console.info(responseObject)
и console.info(responseObject.id)
. Прошу прощения за это. Я думаю, что это связано с моим плохим мастерством. Прошу прощения за это. Но, я хотел бы поддержать вас. Итак, я хотел бы попытаться правильно воспроизвести вашу ситуацию. Когда я смогу правильно воспроизвести это, я хотел бы придумать решение.
@Andrewncf Я снова должен извиниться за свои плохие навыки. Хотя я несколько раз проверял свой скрипт prosoed, я могу подтвердить возвращенные метаданные и идентификатор видео. К сожалению, я не могу повторить I tried to simple use return console.info(responseObject.id); but no luck there.
. Я еще раз глубоко извиняюсь за свое слабое мастерство. Но, я хотел бы поддержать вас. Итак, я хотел бы попробовать правильно воспроизвести I tried to simple use return console.info(responseObject.id); but no luck there.
.
@Andrewncf Спасибо за ответ. Я рад, что ваша проблема была решена. Что касается вашего нового вопроса I would like to assign the id to a constant (or object) to build the url youtube.com/embed{ID} so that the external application can use the youtube video that was uploaded. return responseObject.id.toString()
, я хотел бы вас поддержать. Но, я должен извиниться за мое плохое знание английского языка. К сожалению, я не могу понять ваш новый вопрос. А также, я не могу понять, был ли решен ваш 2-й вопрос. Я думаю, что это связано с моим очень плохим знанием английского языка. Прошу прощения за это.
@Andrewncf Я глубоко извиняюсь, что не могу решить ваши различные вопросы в ближайшее время. Я думаю, что мне нужно больше заниматься английским языком.
Извините, я попытаюсь объяснить в последний раз, и если это не ясно, это нормально. Вы так помогли, и я хотел бы выразить свою признательность. Обычно мое приложение вызывает функцию следующим образом: function add(a){ var answer = a+2 return answer }
Когда веб-сайт вызывает скрипт со значением a=2, он возвращает пользователя с ответом 4. Я просто не уверен, как это работает с console.info(responseObject.id)
Вот почему я пытался return console.info(responseObject.id)
, но внешний приложение не получило возвращаемое значение.
Я более чем счастлив принять ваш ответ и продолжать попытки самостоятельно. Вы действительно очень помогли мне, и я так благодарен. Ваш английский был действительно хорош в общении, я очень ценю вас здесь
@Andrewncf Спасибо за ответ. Я хотел бы поддержать вас. Но, я должен извиниться за мое плохое знание английского, снова. К сожалению, я все еще не могу понять ваш новый вопрос. Я беспокоюсь, что могу побеспокоить вас, потому что я не могу решить ваши различные вопросы в ближайшее время. Итак, в этом случае я хотел бы порекомендовать опубликовать его как новый вопрос. Таким образом, это поможет многим пользователям найти решение. Если вы можете сотрудничать, чтобы решить ваш новый вопрос, я был бы рад. Можете ли вы сотрудничать, чтобы сделать это?
@Andrewncf Спасибо за ответ. Когда вы разместили его как новый вопрос, я хотел бы попытаться понять его снова.
На самом деле я смог решить свою проблему, написав отдельную функцию, которая находит идентификатор самого нового видео на моем канале и возвращает этот идентификатор обратно в исходное приложение. Вы проделали всю тяжелую работу, и еще раз спасибо за то, что так много мне помогли. Это то, что я использовал для получения идентификатора, средний вариант получения загрузок
@Andrewncf Спасибо за ответ. Я рад, что ваш новый вопрос был решен.
Во-первых, я прошу прощения, что мой ответ не был полезен для вашей ситуации. И я должен извиниться за мое плохое знание английского языка. К сожалению, я не могу понять вашу текущую ситуацию из
However, when I try and grab a file from another user in the same folder, the code no longer works.
. Могу я спросить вас о деталях этого? Во-первых, я хотел бы попытаться правильно понять ваш вопрос. Прошу прощения за это.