Quote:
Originally Posted by Nguyen.
looks interesting!
maybe some explanations about your written code or comments?
|
Ok, maybe i just need to change the way the last part was made, we can divide the scripting parts in small objectives to achieve a bigger one (obtaining full video and audio)
Objectives:
1) Download header file and fragments files
3) Append fragment file to header file in order.
So lets begin:
Download header file
Axios is a library that runs in node that lets us make http requests, axios sintax is very simple, it needs:
- an URL
- a method (POST / GET / PATCH ...)

- request Config --
My code seems a bit messy because of the use of functions that call functions, let me simplify it a bit
Code:
axios.get(request(header(MediaType.video)),{responseType: 'arraybuffer'})
is equal to:
Code:
axios.get("siteurl/init-v1-x3.mp4"),{responseType: 'arraybuffer'})
Response type is needed because i got lots of bugs when saving file if not present.
What i did here to prevent hard coding every url that i need to request something, i split functionality in a bunch of functions.
If not familiar with javascript es6, this code is similar
Code:
const header = (type)=>`init-${type}-x3.mp4`;
to something like this in another language
Code:
function getHeader(type){
return "init-"+type+"-x3.mp4"
}
Yes i should named it getHeaderNameByVideoType or sth like this but it is what it is lol.
Moving on those functions construct our request URL based on params that we provided
So taking that in mind
Code:
axios.get(codeThatConstructOurURLForVideoHeaderFile()),{responseType: 'arraybuffer'})
axios.get(codeThatConstructOurURLForAudioHeaderFile()),{responseType: 'arraybuffer'})
Seems a bit nice.
Now the tricky part of this, since we are making a request to a web server, we cannot be sure of how long it will take that request to be finished, so we need to work async.
Luckily for us, axios and many more libraries use promises.
If you are not familiar with promises i will try to explain what they are in a few words: Its a function that is called async (meaning its execution won't halt the code untils is finished) and calls a success function or a fail function.
You can find more about promises here:
Looking back at our code
Code:
axios.get(codeThatConstructOurURLForVideoHeaderFile()),{responseType: 'arraybuffer'}).then((response)=>{
//function that is called when a promise complete successfully
//here we save our file yay!
}).catch(e=>{
//function that is called when something go wrong, where e is the error
//here we retry or end
})
Saving our file is supper easy but there is a catch it may be async or sync, how we decide which one to use?
Well we know that our files should be written sequentially like this:
VIDEO.mp4
--VIDEO-HEADER
--VIDEO-FRAGMENT-1
--VIDEO-FRAGMENT-2
AUDIO.mp4
--AUDIO-HEADER
--AUDIO-FRAGMENT-1
--AUDIO-FRAGMENT-2
Using async functions can mess up the order if not used correctly.
Example:
function saveFragmentAsync(fragmentData){
fs.saveFileAsync("video.mp4",fragmentData);
}
saveFragmentAsync("VIDEO-HEADER");
saveFragmentAsync("VIDEO-FRAGMENT-1");
saveFragmentAsync("VIDEO-FRAGMENT-2");
saveFragmentAsync("VIDEO-FRAGMENT-3");
Could result in a file looking like this:
video.mp4
--VIDEO-FRAGMENT-2
--VIDEO-HEADER
--VIDEO-FRAGMENT-1
--VIDEO-FRAGMENT-3
Wait what? how?, using async functions doesn't guarantee to be run in the order that was provided, we can in fact save header and fragments in different files and construct with them our final file, but that seems like a lot of work and don't want that (of course its not but is more code).
So we decided to save our files sync
Code:
fs.appendFileSync("movie.mp4",res.data); //halt until saved to disk
We wait for the first two files headers to be downloaded (audioheader,videoheader)
Using Promise.all(arrayOfPromises)
And then we proceed to download each fragment, wait until saved to the end of the corresponding file (audio or video).
And thats it work done.
Code:
//ask a webserver for video fragment i, and save it to disk
function getVideoFragment(i){
axios.get("urlforvideofragment i"),{responseType: 'arraybuffer'}).then(res => {
//save fragment to end of header file sync
fs.appendFileSync("movie.mp4",res.data);
console.log("Saving video fragment " + i);
if(i <= maxFragments){
//call recursive if not finished yet
getVideoFragment(i+1);
}
}
);
}