Video's full path with Node.js - javascript

I'm building a video player in node.js with nw.js. It will run offline.
One of the features I'd like to incorporate on this application is the possibility of to play the video dragging and drop it into a "box".
The restriction I'm facing on this implementation is the necessity of encode the video in order to play it, using, for example, the function readAsDataURL(). As discussed in this post, it is not possible to get the fullpath of a file.
"Upload" the entire video, for me, doesn't make sense as long it is already stored in the user's hd.
If he/she try to play The Big Bang Theory (about 20 minutes), it won't be problem to wait 2 or 3 minutes, differently of try to watch The Lord of Rings.
Is there good workaround to deal with this problem?
I appreciate any help.
UPDATE:
I was thinking about the copy and paste of file in a field, as long as with this action is possible to get its URL. But it is not the best thing in terms of user experience...

I've managed. I've changed readAsDataURL() for createObjectURL().
For the sake of reference, my code
var video = document.createElement("video");
video.controls = true;
document.body.appendChild(video);
video.src = (window.URL||window.webkitURL).createObjectURL(file);
video.play();
Now, the The Lord of Rings marathon of my users is saved.

Related

How To Obtain YouTube Video Download Url Just Like KeepVid (2017)?

I'm writing a youtube video downloader. Let's use this video as an example:
https://www.youtube.com/watch?v=_UbDeqPdUek
When researching how to grab a YouTube video's url, I came across a snippet of code right here on stackoverflow:
(function() {
return ytplayer.config.args.adaptive_fmts
.split(',')
.map(item => item
.split('&')
.reduce((prev, curr) => (curr = curr.split('='),
Object.assign(prev, { [curr[0]]: decodeURIComponent(curr[1]) })
), {})
)
.reduce((prev, curr) => Object.assign(prev, {
[curr.quality_label || curr.type]: curr
}), {});
})();
Execute this in the chrome dev console on the youtube url above, and you'll see that it will spew forth an object with information, including video urls.
The 'url' property within the '720p' property, is the following:
https://r2---sn-5hne6nlk.googlevideo.com/videoplayback?mn=sn-5hne6nlk&ip=92.111.133.132&mm=31&sparams=clen%2Cdur%2Cei%2Cgir%2Cid%2Cinitcwndbps%2Cip%2Cipbits%2Citag%2Ckeepalive%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Crequiressl%2Csource%2Cexpire&itag=247&mime=video%2Fwebm&dur=250.800&id=o-AEgCrHyMCCJXgH39WmxsSwNs01bFa3BDVFEIzgAyrthL&mv=m&pl=18&mt=1500667926&requiressl=yes&ms=au&expire=1500689653&initcwndbps=1997500&keepalive=yes&key=yt6&ei=lWByWcWwI4Th1gKa2aDoCg&signature=596BF2603202A1BC60493C8263928FB365A14B2A.92D082149A543786BA5C29A547A8F78DE9346F95&source=youtube&clen=47937010&gir=yes&ipbits=0&lmt=1449652247373936
When I paste this url into a chrome tab, it starts playing the video in a barebones window. You can use this link to download the video. The problem is, the video has no sound!
When I use keepvid to download the video, it will have the following url on the 720p download button:
https://r17---sn-o097znll.googlevideo.com/videoplayback?lmt=1470986968011625&mt=1500670510&dur=250.891&itag=22&ipbits=0&ms=au&sparams=dur%2Cei%2Cid%2Cip%2Cipbits%2Citag%2Clmt%2Cmime%2Cmm%2Cmn%2Cms%2Cmv%2Cpl%2Cratebypass%2Crequiressl%2Csource%2Cexpire&ei=pWpyWZ75BZyf1gLf6rXQCA&id=o-AMPIR2-sd--NM8eDZyPKMqOu1B5qqSkBd1brw-H44ARx&pl=24&mn=sn-o097znll&mm=31&source=youtube&signature=6F5B6D2EFCF5CD600D9B12C984A19DBA58AC6A7E.CC2EE5E63809D4C9A07BB2C194328C7825015976&ratebypass=yes&mv=m&mime=video%2Fmp4&ip=159.253.144.86&requiressl=yes&key=yt6&expire=1500692229&title=Cubs+Meet+Adult+Tiger+For+The+First+Time+-+Tigers+About+The+House+-+BBC
The differences between both urls (and the query params) are small. But the fact is that keepvid's url works better than mine:
It spews up the file as a download, rather than playing it in the browser.
It has sound.
For all of your convenience, here are the url-decoded, formatted versions of these urls, with the parameters alphabetically ordered.
My url which I got from the js snippet above, with sound not working:
https://r2---sn-5hne6nlk.googlevideo.com/videoplayback
clen=47937010
dur=250.800
ei=lWByWcWwI4Th1gKa2aDoCg
expire=1500689653
gir=yes
id=o-AEgCrHyMCCJXgH39WmxsSwNs01bFa3BDVFEIzgAyrthL
initcwndbps=1997500
ip=92.111.133.132
ipbits=0
itag=247
keepalive=yes
key=yt6
lmt=1449652247373936
mime=video/webm
mm=31
mn=sn-5hne6nlk
ms=au
mt=1500667926
mv=m
pl=18
requiressl=yes
signature=596BF2603202A1BC60493C8263928FB365A14B2A.92D082149A543786BA5C29A547A8F78DE9346F95
source=youtube
sparams=clen,dur,ei,gir,id,initcwndbps,ip,ipbits,itag,keepalive,lmt,mime,mm,mn,ms,mv,pl,requiressl,source,expire
The url which I got from keepvid, with sound working:
https://r17---sn-o097znll.googlevideo.com/videoplayback
dur=250.891
ei=pWpyWZ75BZyf1gLf6rXQCA
expire=1500692229
id=o-AMPIR2-sd--NM8eDZyPKMqOu1B5qqSkBd1brw-H44ARx
ip=159.253.144.86
ipbits=0
itag=22
key=yt6
lmt=1470986968011625
mime=video/mp4
mm=31
mn=sn-o097znll
ms=au
mt=1500670510
mv=m
pl=24
ratebypass=yes
requiressl=yes
signature=6F5B6D2EFCF5CD600D9B12C984A19DBA58AC6A7E.CC2EE5E63809D4C9A07BB2C194328C7825015976
source=youtube
sparams=dur,ei,id,ip,ipbits,itag,lmt,mime,mm,mn,ms,mv,pl,ratebypass,requiressl,source,expire
title=Cubs Meet Adult Tiger For The First Time - Tigers About The House - BBC
As you can see, the urls/parameters are very similar. But how does keepvid manage to produce a file url that has the sound working, while my js snippet craps out on me without audio?
The urls have a signature as a parameter. This is likely the signature for (some of the) query parameters itself. Changing something small in a parameter (delete it, or change its value), results in the url getting access denied. This makes it hard to experiment with it.
The js snippet simply accesses an online variable and digs the video info from it. But what's the snippet missing that's causing its urls to refer to soundless videos?
Can anybody help me to programmatically obtain a url just like keepvid's, which will result in a downloaded file with working audio?
[Update]
I've just learned you can grab video info like such:
http://youtube.com/get_video_info?video_id=_UbDeqPdUek
It yields a big file with loads of info, that I haven't figured out how to parse yet.
I must be on the right path, because this is how youtube-dl is doing it. And that program works flawlessly.
I suppose I could simply reverse engineer youtube-dl (costs time). Or even call it from my C# program using Process (makes me dependent on it).
But that still leaves me with the question of how a person would figure this out on their own, if no help was available?
Youtube has 2 type of streams - multiplexed and adaptive. First one has both video and sound, second one only has either of two. Since they are being phased out, multiplexed streams are typically of much lower quality than their adaptive counterparts. What KeepVideo does is present you with the old multiplexed format.
Besides that, on a big portion of videos Youtube uses signature ciphering which adds another pretty massive step to retrieving stream URLs. I don't recommend doing this on your own.
You can check out YoutubeExplode which is a library that lets you query and download videos. You can also check out this sample project which downloads and multiplexes videos using YoutubeExplode and ffmpeg.
But that still leaves me with the question of how a person would figure this out on their own, if no help was available?
Open Chrome developer console and keep inspecting the Network tab until you start noticing patterns.

HTML5 audio how to prevent browser microphones pick up all sounds

In my sample asp.net/vb.net project for HTML5 audio, using Matt Diamond's recorder.js, when I grant any browser access to my microphone, I can hear every noise around me in the headset speakers (e.g., someone typing next to me, people speaking, etc). I'm using a Logitech USB headset, but am not sure the specific model as they're provided through work.
Does anyone know if this is a browser-related issue with the microphone (or possibly resulting from the headset I'm using)? I'm trying to find a different headset to test with, but work typically buys the same model for everyone.
I've tried a few other sites that have demos for recording and play back, and can still hear everything around me once I grant the microphone access (although some demos seem do better at not picking up the background noises).
My knowledge of audio is very limited as I've never worked with audio at the level of normalizing, setting gain, etc. Any resources or suggestions would be greatly appreciated!
I can include a copy of the aspx and vb.net pages from my sample project if that would be helpful. Thanks!
Well, the issue turned out to be my fault due to uncommenting a line of Javascript that caused the audio to feedback directly. Guess that's part of learning something new. :)
Here's the function I used from Matt Diamond's example with the line commented out that I must have incorrectly uncommented at some point...
function startUserMedia(stream) {
var input = audio_context.createMediaStreamSource(stream);
console.log('Media stream created.');
// Uncomment if you want the audio to feedback directly
// input.connect(audio_context.destination);
try {
recorder = new Recorder(input);
} catch (e) {
alert('Error: Unable to record. Please check your sound settings, and allow the browser access to your microphone when prompted.');
console.log('Error: Recorder object could not be created. Msg: ' + e.toString());
}
}
Thank you for the responses that were provided! I'm sure I'll have more audio questions to come, lol.

SoundManager2 onid3() not firing

I'm building a simple Javascript jukebox using the latest SoundManager2 for audio playback, with local MP3 files being the source. I've got file loading and playing sorted, and at the moment I'm trying to get access to the ID3 info of these MP3 files, but the onid3() callback is not firing. I'm using Flash and have verified that ID3 info is present in the files. Below is my implementation of onid3():
function playNextSongInQueue()
{
// Get the first element of the songQueue array
var nextSongInQueue = songQueue.shift();
// Start playback from the queue
var jukeboxTune = soundManager.createSound({
id: 'currentTune',
url: 'audio/' + nextSongInQueue.name,
onload: function() {
this.play();
},
onid3: function() {
alert('ID3 present!');
},
onfinish: function() {
this.destruct(); // Destroy this sound on finish
songFinish(); // Run the songFinish() function, so decide what to do next
}
});
jukeboxTune.load();
//jukeboxTune.play(); // The jukebox running!
songPlaying = true; // Set songPlaying flag
updateSongQueueDisplay(); // Refresh the song queue display (for debug)
return nextSongInQueue.name;
}
The other callbacks work fine, but the onid3() alert never comes up. I even separated the load and play portions of audio playback to see if that helped. SoundManager spots that onid3() is there because it switches usePolicyFile to true - seeing as the MP3s are local I am assuming I don't need to worry about the cross-domain XML file.
Can anybody shed light on why this isn't working? I've scoured Google looking for implementations that work but have come up with nothing helpful. I've seen Jacob Seidelin's pure Javascript workaround but would rather stick with SoundManager if possible, and would rather not use a PHP solution.
Thanks,
Adam
This problem is probably too esoteric for any solid answers, so I decided to investigate possible Javascript solutions outside the SM2 library.
I started with Nihilogic's library for reading ID3v1 tags (at http://blog.nihilogic.dk/2008/08/reading-id3-tags-with-javascript.html), but moved to antimatter15's js-id3v2 library (https://github.com/antimatter15/js-id3v2) as it can read ID3v2 tags. Adapting code from the provided example I have managed to successfully parse the main tags required when the MP3s are loaded via the <input> control.
For local files, i speak of "user local files" (not "server" local files) i get some success with id3v2.js
To get ID3, SM2 need a cross domain on the mp3 host, if it's another domain.
Plus i have encountered difficulties with Soundcloud as they redirect MP3 to dynamic Amazon S3 storage... so i have to do a PHP script to guest final URL and then SM2 can get proper crossdomain.xml (Check https://getsatisfaction.com/schillmania/topics/displaying_waveformdata_of_soundcloud_hosted_track_prompts_securityerror_error_2122 )
The problem is both S3 links and local user files (blob) do have a short expiration delay.
Good luck !

I have a JW Player implementation that won't work 'locally'

Users run my HTML files locally, straight from a CD.
I want to allow them to choose a bunch of videos and create a playlist on the fly.
This works very well if I run a web server but when I run the HTML itself it fails.
The player is created (using swfobject) and all my other code runs but playerReady never fires so I can never get the current play list to add to it.
Any ideas on how I can fix this or, more likely, work around it?
If the player is created, but you're not getting a playerReady, one of two things could be happening.
There's another playerReady on the page that's catching your playerReady. Make sure that there's just one playerReady on the page.
You haven't enabled JavaScript access for Flash. The code for that would look like this:
SWFObject:
var so = new SWFObject('player.swf','ply','470','320','9','#000000');
so.addParam('allowfullscreen','true');
so.addParam('allowscriptaccess','always');
so.addParam('wmode','opaque');
so.addVariable('file','video.flv');
so.write('mediaspace');
I should also note that there are some additional Flash security restrictions because you're accessing the player from disk. Namely, you can't access both a disk source and a network source (the Internet) simultaneously.
Best,
Zach
Developer, LongTail Video

Html5 Audio plays only once in my Javascript code

I have a dashboard web-app that I want to play an alert sound if its having problems connecting. The site's ajax code will poll for data and throttle down its refresh rate if it can't connect. Once the server comes back up, the site will continue working.
In the mean time I would like a sound to play each time it can't connect (so I know to check the server). Here is that code. This code works.
var error_audio = new Audio("audio/"+settings.refresh.error_audio);
error_audio.load();
//this gets called when there is a connection error.
function onConnectionError() {
error_audio.play();
}
However the 2nd time through the function the audio doesn't play. Digging around in Chrome's debugger the 'played' attribute in the audio element gets set to true. Setting it to false has no results. Any ideas?
I encountered this just today, after more searching I found that you must set the source property on the audio element again to get it to restart. Don't worry, no network activity occurs, and the operation is heavily optimized.
var error_audio = new Audio("audio/"+settings.refresh.error_audio);
error_audio.load();
//this gets called when there is a connection error.
function onConnectionError() {
error_audio.src = "audio/"+settings.refresh.error_audio;
error_audio.play();
}
This behavior is expressed in chrome 21. FF doesn't seem to mind setting the src twice either!
Try setting error_audio.currentTime to 0 before playing it. Maybe it doesn't automatically go back to the beginning
You need to implement the Content-Range response headers, since Chrome requests the file in multiple parts via the Range HTTP header.
See here: HTML5 <audio> Safari live broadcast vs not
Once that has been implemented, both the play() function and setting the currentTime property should work.
Q: I’VE GOT AN AUDIOBUFFERSOURCENODE, THAT I JUST PLAYED BACK WITH NOTEON(), AND I WANT TO PLAY IT AGAIN, BUT NOTEON() DOESN’T DO ANYTHING! HELP!
A: Once a source node has finished playing back, it can’t play back more. To play back the underlying buffer again, you should create a new AudioBufferSourceNode and call noteOn().
Though re-creating the source node may feel inefficient, source nodes are heavily optimized for this pattern. Plus, if you keep a handle to the AudioBuffer, you don't need to make another request to the asset to play the same sound again. If you find yourself needing to repeat this pattern, encapsulate playback with a simple helper function like playSound(buffer).
Q: WHEN PLAYING BACK A SOUND, WHY DO YOU NEED TO MAKE A NEW SOURCE NODE EVERY TIME?
A: The idea of this architecture is to decouple audio asset from playback state. Taking a record player analogy, buffers are analogous to records and sources to play-heads. Because many applications involve multiple versions of the same buffer playing simultaneously, this pattern is essential.
source:
http://updates.html5rocks.com/2012/01/Web-Audio-FAQ
You need to pause the audio just before its end and change the current playing time to zero, then play it.
Javascript/Jquery to control HTML5 audio elements - check this link - explains How to handle/control the HTML5 audio elements?. It may help you!
Chrome/Safari have fixed this issue in newer versions of the browser and the above code now works as expected. I am not sure the precise version it was fixed in.

Categories

Resources