Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get video height and width from a MP4 URL with pure ecmascript and without browser support for h.264?

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.

like image 471
user2284570 Avatar asked Sep 14 '14 22:09

user2284570


3 Answers

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"
like image 100
dandavis Avatar answered Sep 19 '22 08:09

dandavis


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.
like image 24
Agamemnus Avatar answered Sep 22 '22 08:09

Agamemnus


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>
like image 26
antishok Avatar answered Sep 19 '22 08:09

antishok