-
-
Save soygul/42677432fa89df7fd783e0232a43a8cf to your computer and use it in GitHub Desktop.
// YouTube API video uploader using JavaScript/Node.js | |
// You can find the full visual guide at: https://www.youtube.com/watch?v=gncPwSEzq1s | |
// You can find the brief written guide at: https://quanticdev.com/articles/automating-my-youtube-uploads-using-nodejs | |
// | |
// Upload code is adapted from: https://developers.google.com/youtube/v3/quickstart/nodejs | |
const fs = require('fs'); | |
const readline = require('readline'); | |
const assert = require('assert') | |
const {google} = require('googleapis'); | |
const OAuth2 = google.auth.OAuth2; | |
// video category IDs for YouTube: | |
const categoryIds = { | |
Entertainment: 24, | |
Education: 27, | |
ScienceTechnology: 28 | |
} | |
// If modifying these scopes, delete your previously saved credentials in client_oauth_token.json | |
const SCOPES = ['https://www.googleapis.com/auth/youtube.upload']; | |
const TOKEN_PATH = '../' + 'client_oauth_token.json'; | |
const videoFilePath = '../vid.mp4' | |
const thumbFilePath = '../thumb.png' | |
exports.uploadVideo = (title, description, tags) => { | |
assert(fs.existsSync(videoFilePath)) | |
assert(fs.existsSync(thumbFilePath)) | |
// Load client secrets from a local file. | |
fs.readFile('../client_secret.json', function processClientSecrets(err, content) { | |
if (err) { | |
console.log('Error loading client secret file: ' + err); | |
return; | |
} | |
// Authorize a client with the loaded credentials, then call the YouTube API. | |
authorize(JSON.parse(content), (auth) => uploadVideo(auth, title, description, tags)); | |
}); | |
} | |
/** | |
* Upload the video file. | |
* | |
* @param {google.auth.OAuth2} auth An authorized OAuth2 client. | |
*/ | |
function uploadVideo(auth, title, description, tags) { | |
const service = google.youtube('v3') | |
service.videos.insert({ | |
auth: auth, | |
part: 'snippet,status', | |
requestBody: { | |
snippet: { | |
title, | |
description, | |
tags, | |
categoryId: categoryIds.ScienceTechnology, | |
defaultLanguage: 'en', | |
defaultAudioLanguage: 'en' | |
}, | |
status: { | |
privacyStatus: "private" | |
}, | |
}, | |
media: { | |
body: fs.createReadStream(videoFilePath), | |
}, | |
}, function(err, response) { | |
if (err) { | |
console.log('The API returned an error: ' + err); | |
return; | |
} | |
console.log(response.data) | |
console.log('Video uploaded. Uploading the thumbnail now.') | |
service.thumbnails.set({ | |
auth: auth, | |
videoId: response.data.id, | |
media: { | |
body: fs.createReadStream(thumbFilePath) | |
}, | |
}, function(err, response) { | |
if (err) { | |
console.log('The API returned an error: ' + err); | |
return; | |
} | |
console.log(response.data) | |
}) | |
}); | |
} | |
/** | |
* Create an OAuth2 client with the given credentials, and then execute the | |
* given callback function. | |
* | |
* @param {Object} credentials The authorization client credentials. | |
* @param {function} callback The callback to call with the authorized client. | |
*/ | |
function authorize(credentials, callback) { | |
const clientSecret = credentials.installed.client_secret; | |
const clientId = credentials.installed.client_id; | |
const redirectUrl = credentials.installed.redirect_uris[0]; | |
const oauth2Client = new OAuth2(clientId, clientSecret, redirectUrl); | |
// Check if we have previously stored a token. | |
fs.readFile(TOKEN_PATH, function(err, token) { | |
if (err) { | |
getNewToken(oauth2Client, callback); | |
} else { | |
oauth2Client.credentials = JSON.parse(token); | |
callback(oauth2Client); | |
} | |
}); | |
} | |
/** | |
* Get and store new token after prompting for user authorization, and then | |
* execute the given callback with the authorized OAuth2 client. | |
* | |
* @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for. | |
* @param {getEventsCallback} callback The callback to call with the authorized | |
* client. | |
*/ | |
function getNewToken(oauth2Client, callback) { | |
const authUrl = oauth2Client.generateAuthUrl({ | |
access_type: 'offline', | |
scope: SCOPES | |
}); | |
console.log('Authorize this app by visiting this url: ', authUrl); | |
const rl = readline.createInterface({ | |
input: process.stdin, | |
output: process.stdout | |
}); | |
rl.question('Enter the code from that page here: ', function(code) { | |
rl.close(); | |
oauth2Client.getToken(code, function(err, token) { | |
if (err) { | |
console.log('Error while trying to retrieve access token', err); | |
return; | |
} | |
oauth2Client.credentials = token; | |
storeToken(token); | |
callback(oauth2Client); | |
}); | |
}); | |
} | |
/** | |
* Store token to disk be used in later program executions. | |
* | |
* @param {Object} token The token to store to disk. | |
*/ | |
function storeToken(token) { | |
fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => { | |
if (err) throw err; | |
console.log('Token stored to ' + TOKEN_PATH); | |
}); | |
} |
Thanks for the reply, interesting as I've reverted back to your code and still had the same issue, I'll try a different account.
Thanks again
I'm getting Authorize this app by visiting this url:...
And when I try to autorize, it's
Access blocked: test has not completed the Google verification process
Clearly, I miss something on console.cloud.google.com/apis/credentials
, but what's that?
Solution:
https://www.youtube.com/watch?v=bkZns_VOB6I
I had to add a test email on Oauth consent screen. (I tought I alreday added one)
You need to do the authorization using the project owner's account. Or else, you can add a test user and test things that way as you did.
If you are using oauth2 and already handling token creation part then here is a working snippet for uploading videos to youtube
const fs = require('fs');
const { google } = require('googleapis');
const categoryIds = {
Entertainment: 24,
Education: 27,
ScienceTechnology: 28
}
const videoFilePath = './videoplayback.mp4'
const thumbFilePath = '../thumb.png'
function uploadVideo(auth, title, description, tags) {
let oauth2Client = new google.auth.OAuth2("158953543582-aikird8t9gm85t1mlg972204l0rhdnlj.apps.googleusercontent.com", "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", "localhost");
oauth2Client.setCredentials({ access_token: "ya29.a0AfB_byDv8Y6KR9mN1MO-ZggytPWRaJpR5Doj_WlqaeCmaH39ZbHeFpKWxo4zX36NpoWfYdYaupo1qhzO119foe-e9_Gm0Fz9ctUZ9l9H3Y3fllyuIb1j8sJPWgWMYXWAUNXaKuiMn0nTBzfWjvz4MMtN24isM3V1OZvfaCgYKAZESARASFQHGX2MimMwiIh_IYu8cvcAEQs9GLg0171" });
const service = google.youtube({
version: 'v3',
auth: oauth2Client
});
// const oauth2Client = new OAuth2("158953543582-aikird8t9gm85t1mlg972204l0rhdnlj.apps.googleusercontent.com", "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", "localhost");
// oauth2Client.setCredentials({
// access_token: "ya29.a0AfB_byBlkvayDllVA0bwvqiDj_TLfGJskEcqpYEGwWgDxTp54XdPdU35CUek7cSo5J3V5XAcxS4bL7DPXG4wCM-fNFzNEdy4nrGp5nXYyQMCaOZ6ID-F9aFW2QkkFkc8WbhPlfpQBULDwZwooaqkuFt3NJ2lB7Fi-OCRaCgYKASoSARASFQHGX2Mi6zCK61ySM_w9KpCuLJRsPg0171"
// })
service.videos.insert({
auth: oauth2Client,
// auth: {
// access_token: "ya29.a0AfB_byBlkvayDllVA0bwvqiDj_TLfGJskEcqpYEGwWgDxTp54XdPdU35CUek7cSo5J3V5XAcxS4bL7DPXG4wCM-fNFzNEdy4nrGp5nXYyQMCaOZ6ID-F9aFW2QkkFkc8WbhPlfpQBULDwZwooaqkuFt3NJ2lB7Fi-OCRaCgYKASoSARASFQHGX2Mi6zCK61ySM_w9KpCuLJRsPg0171"
// },
// auth: "ya29.a0AfB_byBlkvayDllVA0bwvqiDj_TLfGJskEcqpYEGwWgDxTp54XdPdU35CUek7cSo5J3V5XAcxS4bL7DPXG4wCM-fNFzNEdy4nrGp5nXYyQMCaOZ6ID-F9aFW2QkkFkc8WbhPlfpQBULDwZwooaqkuFt3NJ2lB7Fi-OCRaCgYKASoSARASFQHGX2Mi6zCK61ySM_w9KpCuLJRsPg0171",
part: 'snippet,status',
requestBody: {
snippet: {
title,
description,
tags,
categoryId: categoryIds.ScienceTechnology,
defaultLanguage: 'en',
defaultAudioLanguage: 'en'
},
status: {
privacyStatus: "private"
},
},
media: {
body: fs.createReadStream(videoFilePath),
},
}, function (err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
console.log(response.data)
console.log('Video uploaded. Uploading the thumbnail now.')
service.thumbnails.set({
auth: auth,
videoId: response.data.id,
media: {
body: fs.createReadStream(thumbFilePath)
},
}, function (err, response) {
if (err) {
console.log('The API returned an error: ' + err);
return;
}
console.log(response.data)
})
});
}
uploadVideo("", "title num1", "desc denge abhi", "hashta chalega")
After following the provided url to login and performing all the steps , I get redirected to a localhost page but it just says " this site can't be reached" please help
@Shujaagideon I ran into the same problem too. "this site can't be reached" page is meant to be that way. Look into the URL that says "http://localhost/?code=**ThisIsTheCode**&scope=https://www.googleapis.com/auth/youtube.upload" copy the code portion and paste into the command line to proceed. It took me a while to realize that's what they wanted. Hope this helps!
It doesn't work for me
any help pleaze.
It works fine for me as of today.