Upload a video to youtube with node.js - node.js

I've made some headway with the official Google API node client but I've reached a bit of a dead end figuring out how to get my video file up to youtube.
I have a video: example.mp4
I have this code:
OAuth2Client = googleapis.OAuth2Client;
var oauth2Client = new OAuth2Client('XXXXXX', 'XXXXXXX', 'http://callback_url');
googleapis.discover('youtube', 'v3').execute(function(err, client) {
if (err) console.log(err);
// I think the following is the bones of what I want to do
client.youtube.videos.insert({}).execute(function(err, client) {
if (err) console.log(err);
});
});
I only get an error using the insert method (which I expected with no params passed), the client initialises and returns fine.
I'm not sure how to pass the video (in the same directory as the script) to YouTube. Just a pointer would be greatly appreciated.

How about this code:
var googleapis = require('googleapis');
googleapis.discover('youtube', 'v3').execute(function(err, client) {
var metadata = {
snippet: { title:'title', description: 'description'},
status: { privacyStatus: 'private' }
};
client
.youtube.videos.insert({ part: 'snippet,status'}, metadata)
.withMedia('video/mp4', fs.readFileSync('user.flv'))
.withAuthClient(auth)
.execute(function(err, result) {
if (err) console.log(err);
else console.log(JSON.stringify(result, null, ' '));
});
});

You could use this package to do that:
https://github.com/h2non/youtube-video-api

This code works for me:
var file_reader = fs.createReadStream(file_path, {encoding: 'binary'});
var file_contents = '';
file_reader.on('data', function(data)
{
file_contents += data;
});
file_reader.on('end', function()
{
var xml =
'<?xml version="1.0"?>' +
'<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">' +
' <media:group>' +
' <media:title type="plain">' + title + '</media:title>' +
' <media:description type="plain">' + description + '</media:description>' +
' <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">' + category + '</media:category>' +
' <media:keywords>' + keywords + '</media:keywords>' +
' </media:group>' +
'</entry>';
var boundary = Math.random();
var post_data = [];
var part = '';
part = "--" + boundary + "\r\nContent-Type: application/atom+xml; charset=UTF-8\r\n\r\n" + xml + "\r\n";
post_data.push(new Buffer(part, "utf8"));
part = "--" + boundary + "\r\nContent-Type: video/mp4\r\nContent-Transfer-Encoding: binary\r\n\r\n";
post_data.push(new Buffer(part, 'ascii'));
post_data.push(new Buffer(file_contents, 'binary'));
post_data.push(new Buffer("\r\n--" + boundary + "--"), 'ascii');
var post_length = 0;
for(var i = 0; i < post_data.length; i++)
{
post_length += post_data[i].length;
}
var options = {
host: 'uploads.gdata.youtube.com',
port: 80,
path: '/feeds/api/users/default/uploads?alt=json',
method: 'POST',
headers: {
'Authorization': 'GoogleLogin auth=' + auth_key,
'GData-Version': '2',
'X-GData-Key': 'key=' + exports.developer_key,
'Slug': 'example.mp4',
'Content-Type': 'multipart/related; boundary="' + boundary + '"',
'Content-Length': post_length,
'Connection': 'close'
}
}
var req = http.request(options, function(res)
{
res.setEncoding('utf8');
var response = '';
res.on('data', function(chunk)
{
response += chunk;
});
res.on('end', function()
{
console.log(response);
response = JSON.parse(response);
callback(response);
});
});
for (var i = 0; i < post_data.length; i++)
{
req.write(post_data[i]);
}
req.on('error', function(e) {
console.error(e);
});
req.end();
});

Related

Download many files asynchronously

I want to download all the mp3 files contained in this xml, so I created this code using Node.js and JavaScript:
var https = require('https');
var fs = require('fs');
var xml2js = require('xml2js');
var parser = new xml2js.Parser();
var request = require('request');
const xmlUrl = 'https://deejayreloadedpodcast.maxxer.it/podcast/pinocchio.xml';
var download = async function(url, dest, callback) {
// download if only the file is not existing yet
if(!fs.existsSync(dest)) {
await request.get(url)
.on('error', function(err) {
console.log(err);
})
.pipe(fs.createWriteStream(dest))
.on('close', callback);
}
};
https.get(xmlUrl, function(res) {
var response_data = '';
res.setEncoding('utf8');
res.on('data', function(chunk) {
response_data += chunk;
});
res.on('end', function() {
parser.parseString(response_data, function(err, result) {
if(err) {
console.log('Got error: ' + err.message);
}
else {
var json = JSON.stringify(result, null, 2);
var channels = result['rss']['channel'];
var items = channels[0]['item'];
var urlsTemp = [];
var namesTemp = [];
for(var elem in items) {
var obj = items[elem];
var name = obj['title'][0];
var url = obj['enclosure'][0]['$']['url'];
urlsTemp.push(url);
namesTemp.push(name);
}
var urls = [];
var names = [];
for(i in urlsTemp) {
urls.push(urlsTemp[i]);
names.push(namesTemp[i]);
}
for(var i = 10; i < 20/*urls.length*/; i++) {
var dirPath = './puntate/';
var filename = names[i] + '.mp3';
download(urls[i], dirPath + filename, function() {
console.log('Finished downloading \'' + filename);
});
}
}
});
});
res.on('error', function(err) {
console.log('Got error: ' + err.message);
});
});
This code takes the contents of the XML file, processes it by saving the links and file names in two arrays (urls and names) and then downloads the audio files.
The problem is that it only works if you download a few mp3s at a time (in the example, there are only 10).
If I let it loop from 0 to the full length of the array urls, the program no longer works. It does not generate errors but saves all mp3s with size 0 (ie empty).
Why? I thought the problem was asynchronous code, but I used async/await in the download method.
What's the problem?
Thank you
var i = 0;
var dirPath = './puntate/';
var filename = names[i] + '.mp3';
var fn = function(i) {
console.log('(A)', i, urls.length);
download(urls[i], dirPath + filename, function() {
console.log('Finished downloading \'' + filename);
console.log('(B)', i, urls.length);
if(i < urls.length) {
i++;
console.log('(C)', i, urls.length);
fn(i);
}
});
}
fn(i);
and:
(A) 0 3095
Finished downloading 'Puntata del 17 Settembre 2018.mp3
(B) 0 3095
(C) 1 3095
(A) 1 3095
I suggest you to modify the for loop, since it gives a synchronous function:
for(var i = 10; i < 20/*urls.length*/; i++) {
var dirPath = './puntate/';
var filename = names[i] + '.mp3';
download(urls[i], dirPath + filename, function() {
console.log('Finished downloading \'' + filename);
});
}
to a continuous passing style:
var i=0; /*i starts from 0*/
var dirPath = './puntate/';
var fn=function(i){
var filename = names[i] + '.mp3';
download(urls[i], dirPath + filename, function() {
console.log('Finished downloading \'' + filename);
/*if not finish downloading all the links*/
if(i<urls.length){
i++;
fn(i);
}
});
}
fn(i);
Here is enhanced code version:
Improvements:
deleted a unneccessary for loop
if file already exists, skip it until the next not exists one and print.
var https = require('https');
var fs = require('fs');
var xml2js = require('xml2js');
var parser = new xml2js.Parser();
var request = require('request');
var urls = [];
var names = [];
const xmlUrl = 'https://deejayreloadedpodcast.maxxer.it/podcast/pinocchio.xml';
var download = async function(url, dest, callback) {
request.get(url)
.on('error', function(err) {
console.log(err);
})
.pipe(fs.createWriteStream(dest))
.on('close', callback);
};
https.get(xmlUrl, function(res) {
var response_data = '';
res.setEncoding('utf8');
res.on('data', function(chunk) {
response_data += chunk;
});
res.on('end', function() {
parser.parseString(response_data, function(err, result) {
if(err) {
console.log('Got error: ' + err.message);
}
else {
var json = JSON.stringify(result, null, 2);
var channels = result['rss']['channel'];
var items = channels[0]['item'];
// var urlsTemp = []; //you don't need both of temp arrays
// var namesTemp = []; //push items directly into urls[] and names[]
for(var elem in items) {
var obj = items[elem];
var name = obj['title'][0];
var url = obj['enclosure'][0]['$']['url'];
urls.push(url);
names.push(name);
}
var i = 0;
var dirPath = './puntate/';
var fn = function(i) {
var filename = names[i] + '.mp3';
var fileExist=fs.existsSync(dirPath + filename);
// skip downloading if the file exists already
if(fileExist){
console.log('File exists', i, urls.length);
i++;
fn(i);
}else{ // download if only the file is not existing yet
console.log('(A)', i, urls.length);
download(urls[i], dirPath + filename, function() {
console.log('Finished downloading \'' + filename);
console.log('(B)', i, urls.length);
if(i < urls.length) {
i++;
console.log('(C)', i, urls.length);
fn(i);
}
});
}
}
fn(i);
}
});
});
res.on('error', function(err) {
console.log('Got error: ' + err.message);
});
});

Jquery rest called Image not dispalyed in sharepoint online page

i am developing an share point hosted online application when i am fetch Picture Library list items successfully.But the Image is not displayed in the page. Here i attached my code whats wrong? Could any one guide to me. I am a new on Share point online App.
function LoadImages() {
appWebUrl = window.location.protocol + "//" + window.location.host + _spPageContextInfo.webServerRelativeUrl;
hostWebUrl = _spPageContextInfo.siteAbsoluteUrl;
$(function () {
var utilTargetsList = "CustomerLicenceGallary";
$.ajax({
url: appWebUrl + "/_api/SP.AppContextSite(#target)/web/lists/getbytitle('" + utilTargetsList + "')/items?#target='" + hostWebUrl + "'",
method: "GET",
headers: {
"accept": "application/json;odata=verbose", "content-type": "application/json;odata=verbose", "X-RequestDigest": jQuery("#__REQUESTDIGEST").val()
},
success: function (d) {
var stringData = JSON.stringify(d);
var jsonObject = JSON.parse(stringData);
var results = jsonObject.d.results;
for (var i = 0; i < results.length; i++) {
jQuery('#Image').attr('src', results[i]["Name"]);
break;
}
},
//success: getitemssucces
error: function (error) {
console.log(JSON.stringify(error.toString()));
}
});
});
}
$(document).ready(function () {
LoadImages();
});
<div> <img id="Image" alt="Image" /></div>
PictureLibrary List
I got answer and working fine thanks all to support.
var arrayOfImageObjects = new Array();
var currentImageIndex = 0;
var hostWebUrl;
var appWebUrl;
function GetImagesAndRotate() {
appWebUrl = window.location.protocol + "//" + window.location.host
+ _spPageContextInfo.webServerRelativeUrl;
hostWebUrl = _spPageContextInfo.siteAbsoluteUrl;
// var url = appWebUrl + "/_api/SP.AppContextSite(#target)/web/lists/getbytitle('CustomerLicenceLibrary')/items?$expand=File"
//url: appWebUrl + "/_api/SP.AppContextSite(#target)/web/lists/getbytitle('" + utilTargetsList + "')/items?$top=1&#target='" + hostWebUrl + "'&$Orderby=ID desc",
jQuery.ajax({
url: appWebUrl + "/_api/SP.AppContextSite(#target)/web/lists/getbytitle('CustomerLicenceLibrary')/items?$expand=File&#target='" + hostWebUrl + "'",
type: "GET",
headers: {
"X-HTTP-Method": "MERGE",
"accept": "application/json;odata=verbose",
"content-type": "application/json;odata=verbose",
"X-RequestDigest": $("#__REQUESTDIGEST").val(),
},
success: function (data) {
var result = data.d.results;
for (var i = 0; i < result.length; i++) {
var image = result[i];
var imageObject = {};
imageObject.Name = image.File.Name;
imageObject.Url = image.File.ServerRelativeUrl;
imageObject.Width = image.File.ImageWidth;
imageObject.Height = image.File.ImageHeight;
arrayOfImageObjects.push(imageObject);
}
setTimeout(NextImage, 5000);
},
error: function () {
alert("request failed");
}
});
}
function NextImage() {
if (currentImageIndex < arrayOfImageObjects.length) {
jQuery('#Image').attr('src', arrayOfImageObjects[currentImageIndex].Url);
currentImageIndex++;
}
else
currentImageIndex = 0;
setTimeout(NextImage, 5000);
}
jQuery(document).ready(function () {
GetImagesAndRotate();
});

how to get the result in nodejs server?

now, help me, I try to post data with ajax to nodejs server.
and server accept the postdata. and now i use http.get to request www.baidu.com, and want to get the html , at last return the html to front.but is error
front ajax
$("#subbtn").click(function(){
var keywords = $("#kw").val();
var target = $("#result");
if (!keywords){
target.html("<font color='#FF0000'>please key words</font>");
}
var keyArr = keywords.replace(/\,+/g, ",").split("\,");
for (var i = 0; i < keyArr.length; i++){
$.ajax({
type: "POST",
url: "http://127.0.0.1:10088",
data : { kw : keyArr[i]},
dataType: "json",
cache: false,
timeout: 5000,
success: function(data) {
alert(data.rank);return false;
// $("#result").append(data.num);
},
error: function(jqXHR, textStatus, errorThrown) {
alert('error ' + textStatus + " " + errorThrown);
}
});
}
});
and the server.js
// Nodejs部分,主要作用是接收前端关键词,抓取百度知道页面。返回页面给前端
var http = require('http');
var cheerio = require('cheerio');
var iconv = require('iconv-lite');
http.createServer(function (req, res) {
res.writeHead(200, { 'Content-Type': 'text/html', 'Access-Control-Allow-Origin' : '*' });
var postData = "";
var ret = 0;
req.setEncoding('utf-8');
req.addListener('data', function(chunk){
postData += chunk;
});
req.addListener('end', function(){
var value = postData.replace(/kw=/, ''), result = 0;
doRequest(value, 0);
});
res.end('{"rank":'+result+'}');
}).listen(10088);
/**
* GET请求Baidu
* #param kw 关键词
* #param page
*/
var doRequest = function(kw, page){
page = page * 10;
var options = {
host: 'zhidao.baidu.com',
port: 80,
path: '/search?word='+kw+'&pn='+page
};
http.get(options, function(res) {
var buffers = [], size = 0;
res.on('data', function(buffer) {
buffers.push(buffer);
size += buffer.length;
});
res.on('end', function() {
var buffer = new Buffer(size), pos = 0;
for(var i = 0, l = buffers.length; i < l; i++) {
buffers[i].copy(buffer, pos);
pos += buffers[i].length;
}
var gbk_buffer = iconv.decode(buffer,'GBK');
$ = cheerio.load(gbk_buffer.toString());
// 获取页面前三个的优质回答
var target = "DARRY RING";
var isBreak = false;
var htmlTop = $("#cluster-items").find(".con-all").slice(0, 3);
htmlTop.each(function(){
var tContent = $(this).text().replace(/\s+/g, "");
tContent = tContent.toLowerCase();
if (tContent.indexOf("darryring") > 0 ){ // 当找到DY的时候,退出循环
isBreak = true;
return false;
}
});
if (isBreak == true){
return {keyword : kw, score : 1};
}
var html = $("#wgt-list").find("dd.answer");
var n = 0;
html.each(function(i, elem){
var content = $(this).text().replace(/\s+/g, "");
content = content.toLowerCase();
if (content.indexOf("darryring") > 0 && n <= html.length ){ // 当找到DY的时候,退出循环
n = i + 1;
return false;
}
});
if(n == 0){
page++;
if (page < 5){
doRequest(kw, page);
}else{
return {keyword : kw, score : 9999};
}
}else{
var num = page + n;
return {keyword : kw, score : num};
}
});
res.on('error', function(e){
console.log("Got error: " + e.message);
})
})
}
Parsing POST data can be tricky business. I recommend using a module to help you out. Formaline has all the bells and whistles you'll need or poor-form is a lighter weight version.

Node.js YouTube API Upload unable to convert video

I'm trying to upload video to youtube programatically. I chose to use Node.js for the task.
I get an XML response as well as an HTTP Status Code of 201 and I see the video appear in video manager, however the video always has the message "Failed (unable to convert video file)".
I can upload the file through YouTube's own uploader on their page and there are no problems. I only have to upload to a single account, so I set up the OAuth2 for the account and stored the refresh token. The refresh token is hard-coded, though I replace it with a variable below.
Does the refresh token need to, itself, be refreshed?
My code:
var qs = require('querystring'),
https = require('https'),
fs = require('fs');
var p_data = qs.stringify({
client_id: myClientID,
client_secret: myClientSecret,
refresh_token: refreshTokenForAccount,
grant_type: 'refresh_token'
});
var p_options = {
host: 'accounts.google.com',
port: '443',
method: 'POST',
path: '/o/oauth2/token',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Content-Length': p_data.length,
'X-GData-Key': myDeveloperKey
}
};
var file_path = process.argv[1] || "video.mp4";
var json = "";
var p_req = https.request(p_options, function(resp){
resp.setEncoding( 'utf8' );
resp.on('data', function( chunk ){
json += chunk;
});
resp.on("end", function(){
debugger;
var access_token = JSON.parse(json).access_token;
var title="test upload1",
description="Second attempt at an API video upload",
keywords="",
category="Comedy";
var file_reader = fs.createReadStream(file_path, {encoding: 'binary'});
var file_contents = '';
file_reader.on('data', function(data)
{
file_contents += data;
});
file_reader.on('end', function()
{
var xml =
'<?xml version="1.0"?>' +
'<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">' +
' <media:group>' +
' <media:title type="plain">' + title + '</media:title>' +
' <media:description type="plain">' + description + '</media:description>' +
' <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">' + category + '</media:category>' +
' <media:keywords>' + keywords + '</media:keywords>' +
' </media:group>' +
'</entry>';
var boundary = Math.random();
var post_data = [];
var part = '';
part = "--" + boundary + "\r\nContent-Type: application/atom+xml; charset=UTF-8\r\n\r\n" + xml + "\r\n";
post_data.push(new Buffer(part, "utf8"));
part = "--" + boundary + "\r\nContent-Type: video/mp4\r\nContent-Transfer-Encoding: binary\r\n\r\n";
post_data.push(new Buffer(part, 'utf8'));
post_data.push(new Buffer(file_contents, 'binary'));
post_data.push(new Buffer("\r\n--" + boundary + "--\r\n\r\n", 'utf8'));
var post_length = 0;
for(var i = 0; i < post_data.length; i++)
{
post_length += post_data[i].length;
}
var options = {
host: 'uploads.gdata.youtube.com',
port: 443,
path: '/feeds/api/users/default/uploads',
method: 'POST',
headers: {
'Authorization': 'Bearer ' + access_token,
'X-GData-Key': myDeveloperKey,
'Slug': 'video.mp4',
'Content-Type': 'multipart/related; boundary="' + boundary + '"',
'Content-Length': post_length,
'Connection': 'close'
}
}
var req = https.request(options, function(res)
{
res.setEncoding('utf8');
console.dir(res.statusCode);
console.dir(res.headers);
var response = '';
res.on('data', function(chunk)
{
response += chunk;
});
res.on('end', function()
{
console.log( "We got response: " );
console.log(response);
});
});
for (var i = 0; i < post_data.length; i++)
{
req.write(post_data[i]);
}
req.on('error', function(e) {
console.error(e);
});
req.end();
});
});
});
p_req.write(p_data);
p_req.end();
The problem was in the file being uploaded.
This line: var file_path = process.argv[1] || "video.mp4"; should have been var file_path = process.argv[2] || "video.mp4";
Note argv[1] is the absolute path to the script being run, argv[2] is the first command line argument passed to the script.
Of course YouTube would fail to convert the "video", it wasn't video at all it was the script being run.

node.js / Youtube API / Upload

Using the following code I'm tring to upload a video youtube via direct upload. I already have the access token (auth_key). I'm pretty sure I'm sending the post data incorrectly...
function upload(auth_key, devKey, callback){
fs.readFile('test.mp4', function(err, movie){
var boundary = randomString();
var xml =
'<?xml version="1.0"?>' +
'<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">' +
'<media:group>' +
'<media:title type="plain">Bad Wedding Toast</media:title>' +
'<media:description type="plain">I gave a bad toast at my friends wedding.</media:description>' +
'<media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">People</media:category>' +
'<media:keywords>toast, wedding</media:keywords>' +
'</media:group>' +
'</entry>'
;
var post_data =
'--' + boundary + '\n' +
'Content-Type: application/atom+xml; charset=UTF-8' + '\n' +
xml + '\n' +
'--' + boundary + '\n' +
'Content-Type: video/mp4' + '\n' +
'Content-Transfer-Encoding: binary' + '\n' +
movie + '\n' +
'--' + boundary + '--' + '\n'
;
var options = {
host: 'uploads.gdata.youtube.com',
port: 443,
path: '/feeds/api/users/default/uploads',
method: 'POST',
headers: {
'Authorization:': 'GoogleLogin auth=' + auth_key,
'GData-Version': '2',
'X-GData-Key': 'key=' + devKey,
'Slug': 'test.mp4',
'Content-Type': 'multipart/related; boundary="' + boundary + '"',
'Content-Length': post_data.length,
'Connection': 'close'
}
}
var req = https.request(options, function(res) {
var response = '';
res.on('data', function(chunk) {
response += chunk;
});
res.on('end', function(){
callback(response);
});
});
if(post_data){
req.write(post_data);
}
req.end();
req.on('error', function(e) {
console.error(e);
});
});
}
Is failing with "Invalid Request"?
You have some errors in your code, the syntax of the html request is missing "\r\n". You should also use the http library and port 80. Your Authorization header is invalid, it should not contain an ":" at the end. And I think the way your are adding the data and calculating the content length also messes things up.
I've successfully uploaded videos to youtube with the following code:
var file_reader = fs.createReadStream(file_path, {encoding: 'binary'});
var file_contents = '';
file_reader.on('data', function(data)
{
file_contents += data;
});
file_reader.on('end', function()
{
var xml =
'<?xml version="1.0"?>' +
'<entry xmlns="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" xmlns:yt="http://gdata.youtube.com/schemas/2007">' +
' <media:group>' +
' <media:title type="plain">' + title + '</media:title>' +
' <media:description type="plain">' + description + '</media:description>' +
' <media:category scheme="http://gdata.youtube.com/schemas/2007/categories.cat">' + category + '</media:category>' +
' <media:keywords>' + keywords + '</media:keywords>' +
' </media:group>' +
'</entry>';
var boundary = Math.random();
var post_data = [];
var part = '';
part = "--" + boundary + "\r\nContent-Type: application/atom+xml; charset=UTF-8\r\n\r\n" + xml + "\r\n";
post_data.push(new Buffer(part, "utf8"));
part = "--" + boundary + "\r\nContent-Type: video/mp4\r\nContent-Transfer-Encoding: binary\r\n\r\n";
post_data.push(new Buffer(part, 'ascii'));
post_data.push(new Buffer(file_contents, 'binary'));
post_data.push(new Buffer("\r\n--" + boundary + "--"), 'ascii');
var post_length = 0;
for(var i = 0; i < post_data.length; i++)
{
post_length += post_data[i].length;
}
var options = {
host: 'uploads.gdata.youtube.com',
port: 80,
path: '/feeds/api/users/default/uploads?alt=json',
method: 'POST',
headers: {
'Authorization': 'GoogleLogin auth=' + auth_key,
'GData-Version': '2',
'X-GData-Key': 'key=' + exports.developer_key,
'Slug': 'video.mp4',
'Content-Type': 'multipart/related; boundary="' + boundary + '"',
'Content-Length': post_length,
'Connection': 'close'
}
}
var req = http.request(options, function(res)
{
res.setEncoding('utf8');
var response = '';
res.on('data', function(chunk)
{
response += chunk;
});
res.on('end', function()
{
console.log(response);
response = JSON.parse(response);
callback(response);
});
});
for (var i = 0; i < post_data.length; i++)
{
req.write(post_data[i]);
}
req.on('error', function(e) {
console.error(e);
});
req.end();
});

Resources