Play audio file from string in JavaScript - javascript

I have the contents of an mp3 file saved as a variable, (this isn't meant to be practical, just for a little project of mine), and I wish to play the contents of this variable as an audio file. This would be a simple task with something like node, but unfortunately I must do this entirely client side.
Please note I can not just save the content of the string as an mp3 file, I need to be able to play it from a variable.
I have looked into this, but from what I have found, it appears that this can not be done. If any of you have a solution, I would appreciate hearing it.

This is not very practical, as you're going to get very high memory footprints within the JS engine and will likely cause unnecessary garbage collection... but it is possible to a base64 encode the MP3 which can then be fed into the src attribute of an <audio> tag.
Because it is unrealistically to provide a base64 encoded MP3 in an answer here I'll provide a Fiddle: https://jsfiddle.net/4t6bg95z/1/
But the gist of the code can be something like:
var audio = document.getElementById('audio');
audio.src = "data:audio/mp3;base64,..."; //This is a base64 encoded string of an MP3 file
window.beep = function() {
audio.play();
}
Obviously, it is much better practice to provide a URL to the audio source instead, as that's the intended usage of the Audio API.

Related

how to store image / video file using gundb?

I know the traditional way is to store image/video file in one place and then just save the reference index into db's table.
Now I am learning about gundb, I can store key-value json type data very easily, but since it is decentralized, if I wanna make a say chatroom app, how should I handle image storing (eg: user's avatar)?
I am also wondering if it is possible to make a movie-sharing app using gundb?
#Retric, great question! I'm not sure why people are downvoting you, they must be haters.
You are right, it is better to store that image/video and reference it via GUN. For videos specifically, WebTorrent/BitTorrent has done P2P video sharing for over a decade now and at one point handled 40% of the world's internet traffic!
However WebTorrent/BitTorrent is not very good with discovering/sharing those URIs (magnet links, etc.) but GUN is. So I'd recommend that as one option.
For images, especially small ones like avatars/icons/profiles, I do often store them in GUN directly by Base64 encoding them (many websites around the world inline images/icons/sprites/avatars into CSS files with base64 data-URLs, except now you could use GUN for this).
If you are interested in this, I wrote a small utility using jQuery that lets you drag&drop images into your website, and it'll auto-resize (pass options to overwrite it) and base64 encode it for you to then save to GUN:
https://github.com/amark/gun/blob/master/lib/upload.js
Here is a small example of how I use it:
$('#profile').upload(function resize(e, up){
if(e.err){ return } // handle error
$('#profile').addClass('pulse'); // css to indicate image processing
if(up){ return up.shrink(e, resize, 64) } // pass it `e` drag&drop/upload event, then I reuse the current function (named resize) as the callback for it, and tell it resize to 64px.
$('#profile').removeClass('pulse'); // css indicate done processing.
$("#profile img").attr('src', e.base64).removeClass('none'); // set photo in HTML!
gun.user().get('who').get('face').get('small').put(e.base64); // save profile thumbnail to GUN
});
Finally, what about storing videos in GUN if you don't want to use BitTorrent?
I would highly recommend using the HLS format to store videos in GUN, this would allow you to do decentralized realtime video streaming. It is a beautifully simple format that allows video streaming to work even from static files, because it stores the video in small chunks that can be streamed - which fits perfectly with GUN.
There already is a JS based video-player for the HLS format:
https://github.com/video-dev/hls.js/
Based off the demo page, you can see an example of how the video is stored, like here on GitHub:
https://github.com/video-dev/streams/tree/master/x36xhzz
(if you click on the m3u8 file, you'll see it has metadata that 720p is stored in url_0 folder, which themselves have sub-files)
Rather than storing the HLS video files on BitTorrent or a centralized server, you could store it in GUN using the same folder structure gun.get('videos').get('x36xhzz').get('url_0').get('url_496').get('193039199_mp4_h264_aac_hd_7.ts').once(function(video_chunk){ passToHLSplayer(video_chunk) }) such that it would be easy for HLS.js to integrate with GUN.
Now you'll have P2P decentralized video streaming!!!
And even cooler, you can combine it with GUN's lib/webrtc adapter and do this fully browser to browser!
I hope this helped.
The thing to understand here is the difference between content addressed space (frozen space) and user space in gun.
Let's say you have some media encoded as base64, and you know its content type (I've used text here to keep example short, but you could use image video etc):
// put avatar in frozen space:
let media = JSON.stringify({ b64 : "U2hlIHdhcyBib3JuIGFuIGFkdmVudHVyZXIuLi4=", type : "text/plain"})
// get hash of stringified media obj using gun's SEA lib:
let mediaID = await SEA.work(media, null, null, {name: "SHA-256"});
// put media in hash-addressed gundb
gun.get('#').get(mediaID).put(media,(r)=>console.log('Media put acknowledged?',r))
For a hypothetical chat app, you could use user space and put the media under the "avatar" name:
// put avatar in user space:
let user = await SEA.pair();
await gun.user().auth(user)
gun.get('~' + user.pub).get('avatar').put('#' + mediaID)
// retrieve a user's avatar
gun.get('~' + usera.pub).get('avatar').once((hashid,k)=>{
gun.get('#').get(hashid).once(media=>{
console.log("Got user's avatar :-)",media)
//do something with media
})
})

Buffering a client-side file download

I have a file which is split up into multiple parts on the server side. The complete file is huge, it can be 10 or more gigabytes in size (that is the reason for splitting it in the first place).
The file is in a specific format, and it has to be processed on the client side before being downloaded.
Now, I know that I can download into a Blob to the client side, do the processing, then download Blobs from there with this approach: JavaScript blob filename without link
The problem here is that I would need to construct a single huge blob from all the file parts on the client side, which I do not want, because it will probably exceed RAM limitations rather quickly.
I would like to download each part of the file individually and then process it and download the "partial" blob. That means that I would need to start a download and then piece by piece add blobs to it until the download is complete.
Is there any possibility of doing this? How? I know that mega.co.nz does something similar with file downloads where they process the file on the client side first (for decryption). Are they using such techniques?
You can save the downloaded parts to localStorage. You will have to serialize each part into a string first; then you can call localStorage.setItem. Your code might look like this:
localStorage.setItem('download-part-' + chunkIndex, chunkDataAsString);
chunkDataAsString = ''; // let the garbage collector collect the large string

Is it possible to cut part of video and upload it on server only with html5 & js

I use Filereader to read local video file (mp4), so I can display it in video tag.
I need to cut part of mp4 file (i.e. from 5 to 10 seconds) and upload it on server.
My current solution: I upload whole video file on server with "from" and "to" parameters, cut it with ffmpeg on server, upload to s3 and return the url video.
Maybe is it possible only with JS/HTML? I found Blob.slice method but i didn't know how to use it to cut video parts.
Thanks!
An mp4 video file is made up of 'atoms' which are like blocks of information or data within a file.
They contain header and metadata about the tracks in the movie (Audio, video, subtitles etc) and also the media data itself.
The concepts are straightforward but an mp4 file is quite involved when you look at one - there is a good example here from the apple developers site (https://developer.apple.com/library/content/documentation/QuickTime/RM/Fundamentals/QTOverview/QTOverview_Document/QuickTimeOverview.html):
If you take a 'slice' of the mp4 file by simply taking bytes from some point in the file to some other point, you can see that you will be missing header information etc depending where you start from, and will also most likely start in the middle of an 'atom'.
Tools like ffmpeg do the hard work to extract and restructure the file when you want to cut part of the video.
There are projects which run ffmpeg in the bowser, but I'm not sure how practical or adopted they are - the one seems pretty popular anyway:
https://github.com/bgrins/videoconverter.js

Replacing audio track of the video

I have a video file "MyVideo.mp4" (*.mp4 is not required. It can be in any others formats) and I have an audio file "MyAudio.mp3".
Does anyone have any ideas how to replace an audio track from the video on the audio file "MyAudio.mp3"?
Demultiplexing + remultiplexing ("splitting" + "recombining") is something you would like to do on server side using a software like FFMpeg or similar.
Doing this is JavaScript will be non-trivial as you would have to parse and save the file formats manually (you must be able to parse all formats you'd support).

audio tag prevent buffer

While using HTML5 audio tag, i am having a problem.
I am using icecast2 server to stream my music.
But the problem is, browser saves the buffer when stream is played. So when the player is paused or the page is refreshed, instead of asking server for the fresh stream, it plays the previously saved buffer only.
As i am playing live stream, i want always fresh stream to be played. What can i do to ensure that??
What i found after browsing is- HTML5 Video: Force abort of buffering
So creating a new audio tag is an option but i am not clear on it and also i dont know if it is a good way.
Probably the most common way to prevent caching of any HTTP resource (text files, images, audio, etc) is to append a meaningless random GET parameter onto the URL. So if your URL is like this:
http://musicserver.com/livestream.mp3
Then you'd do something like this:
http://musicserver.com/livestream.mp3?nocache=12034981237
Where the value of nocache is randomly generated each and every time. Then the browser will treat it as a new unique resource/file.

Categories

Resources