I'm writing a user script for downloading videos. The flash player of the web site use a JSON file.
The purpose of my script is to get the url of the video by downloading and parsing the video according to the web page. Currently it can download an extract the URL of the videos successfully.
The important part of the JSON file look like this :
{
"ammProfile": "AMM-HBBTV",
"version": "VF",
"versionProg": "1",
"VFO": "HBBTV",
"VMT": "mp4",
"VUR": "http://vo.llnwd.net/v2/am/HBBTV/051332-074-A_SQ_2_VF_01464306_MP4-2200_AMM-HBBTV.mp4"
}, {
"ammProfile": "AMM-HBBTV",
"version": "VF",
"versionProg": "1",
"VFO": "HBBTV",
"VMT": "mp4",
"VUR": "http://vo.llnwd.net/v2/am/HBBTV/051332-074-A_EQ_2_VF_01464315_MP4-1500_AMM-HBBTV.mp4"
}
Both URL here are about the same video, this just is just the resolution which change.
So, How I can parse the relevant metadata without downloading the whole file? The standard for the H.264 video codec is very hard to read.
you don't need to load the whole video to get the height:
function getVideoHeight(url, fnCallback){
var video=document.createElement("video");
video.autoplay=true;
video.oncanplay=function(){
fnCallback(this.offsetWidth, this.offsetHeight);
this.src="about:blank";
document.body.removeChild(video);
};
document.body.appendChild(video);
video.src=url;
}
//test:
getVideoHeight(
"http://www.quirksmode.org/html5/videos/big_buck_bunny.mp4",
function(w,h){ alert( w+"X"+h); }
); // shows: "640X360"
You can use the Range HTTP header via XMLHttpRequest to get only a portion of the file:
http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html
For example:
xhr.setRequestHeader ('Range', 'bytes=0-' + (fragment_size - 1))
xhr.setRequestHeader ('Content-Length', fragment_size) // This part isn't absolutely required on most (all?) browsers.
I use the xhr range header to download partial content, and then get the file info using videoconverter.js, a JS version of ffmpeg (whose license you should check if you plan to use any of this).
var videoUrl = 'https://dl.dropboxusercontent.com/u/17698405/bla.mp4';
var cmd = '-i myfile.mp4';
var args = parseArguments(cmd);
var sizeToDownload = 200*1024;
retrieveVideo(videoUrl, sizeToDownload, function(fileData) {
ffmpeg_run({
arguments: args,
files: [{
name: 'myfile.mp4',
data: fileData
}],
print: print,
printErr: print
});
});
function parseArguments(text) {
text = text.replace(/\s+/g, ' ');
var args = [];
text.split('"').forEach(function(t, i) {
t = t.trim();
if ((i % 2) === 1) {
args.push(t);
} else {
args = args.concat(t.split(" "));
}
});
return args;
}
function retrieveVideo(path, fragment_size, callback) {
var xhr = new XMLHttpRequest();
xhr.open("GET", path, true);
xhr.responseType = "arraybuffer";
xhr.setRequestHeader ('Range', 'bytes=0-' + (fragment_size - 1));
xhr.onload = function (oEvent) {
var arrayBuffer = xhr.response;
if (arrayBuffer) {
callback(new Uint8Array(arrayBuffer));
}
};
xhr.send(null);
}
var textarea = document.getElementsByTagName('textarea')[0];
function print(text) {
textarea.value += '> ' + text + '\n';
}
* { box-sizing: border-box }
html,body { height: 100%; margin: 0; padding: 0; overflow: hidden }
textarea { width: 100%; height: 100%; }
<script src="https://rawgit.com/bgrins/videoconverter.js/master/build/ffmpeg-all-codecs.js"></script>
<textarea></textarea>