Uploading Video File on Google Drive to YouTube with Resumable Upload using Google Apps Script

Gists

This is a simple sample script for uploading a video file on Google Drive to YouTube with the resumable upload using Google Apps Script.

When you want to upload a video file to YouTube using Google Apps Script, when YouTube API of Advanced Google services is used, the maximum file size is 5 MB, because, in this case, the video file is uploaded with multipart/form-data. When you want to use a video file with more file size using Google Apps Script, a resumable upload is required to be used. But, unfortunately, in the current stage, the methods of Google Apps Script for uploading large video files are not prepared. And also, when I saw the document of resumable upload on YouTube in the official document, I thought that it might be a bit complicated for understanding the resumable upload process. Ref So, in this post, I would like to introduce a simple sample script for uploading video data of more than 5 MB with the resumable upload using Google Apps Script. In this case, the video file is existing in Google Drive. The video file on Google Drive is uploaded to YouTube using Google Apps Script. When this sample script will help you understand the resumable upload of YouTube, I’m glad.

I have uploaded a file to Google Drive using the resumable upload with Drive API. This experience helped me understand the resumable upload of video data to YouTube.

Usage

1. Upload a video file to Google Drive.

Please upload a sample video file to your Google Drive. In this sample script, the video data of the video file on Google Drive is uploaded to YouTube using Google Apps Script.

2. Create a Google Apps Script project.

Please create a Google Apps Script project. In this case, you can use both the standalone type and the container-bound script type.

3. Enable APIs.

This sample script used Drive API and YouTube API. So, please enable them at Advanced Google services.

4. Sample script.

Please copy and paste the following sample script to the script editor of Google Apps Script.

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;
  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());
    } else if (statusCode == 308) {
      console.log("Upload the next chunk.");
      res2.splice(0, res2.length);
    } else {
      throw new Error(res3.getContentText());
    }
  });

  // 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.
}

5. Testing

When this script is run, you can see the following process in the log.

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": {,,,}
}

IMPORTANT

  • In this sample script, the chunk size is 20 MB as a sample. You can modify this. But, when this size is large, an error might occur. Please be careful about this.
  • If you have no YouTube channel, you cannot upload the video file.
  • When your account is not confirmed by Google side, video data of more than 15 minutes cannot be uploaded. Please be careful about this.
  • In the current stage, the maximum execution time of Google Apps Script is 6 minutes. So, when you want to upload a large video data, the data might not be able to be completely uploaded, because of the maximum execution time. Please be careful about this.
    • If you want to upload the video data with more large size, I think that you can achieve it by executing the script with the time-driven trigger. But, in this case, it is required to modify the above script. Please be careful about this. In this post, the simple sample script is introduced.

References

Testing

  • January 3, 2023: When I tested above sample script, I could confirm that the script worked.

  • January 22, 2023: When I tested above sample script, I could confirm that the script worked.

 Share!