Receive chunks of video and play them in browser - javascript

Base idea: I am creating an app. In which user chooses local file(mp4) in input field(type="file") and then streams the video to other user.
I am thinking to manipulate the file in javascript. And send it chunk by chunk to another user via(datachannels webRTC) then just play it on the other side chunk by chunk.
I understand that i can "assemble" the chunks using - MediaSource API
Questions: How can i split the video in chunks using javascript? I have been googling for a while i can't seem to find a library( maybe i am googling wrong keywords? ).
Thanks!

Use blob#slice to split the video
// simulate a file
blob = new Blob(['ab'])
chunk1 = blob.slice(0, 1)
chunk2 = blob.slice(1, 2)
console.log(blob.size)
console.log(chunk1.size)
console.log(chunk2.size)

Another thing i might think you are interested in is File streaming...
To get a ReadableStream from a blob you could use the hackish why of doing
stream = new Response(blob).body
reader = stream.getReader()
reader.read().then(chunk => spread(chunk))
Another cool library otherwise you can use to stream the blob Is by using Screw-FileReader

What wouldn't be more awesome then using WebTorrent to share the video got everything you need... uses WebRTC...

Related

Receive audio download in chunks and play smoothly with web audio API

I could not really find any way to smoothly get and play audio chunks with Web Audio API. Currently I am simply fetching an audio file from my CDN, but I have tested it on slower internet connections, and as expected it results in a long wait before the audio starts playing.
My code currently is the following:
let context = new AudioContext()
currentsrc = context.createBufferSource()
let audioBuffer = await fetch(songid)
.then(res => res.arrayBuffer())
.then(ArrayBuffer => context.decodeAudioData(ArrayBuffer))
currentsrc.buffer = audioBuffer
currentsrc.connect(context.destination)
currentsrc.start()
This way the script is waiting till the entire audio is downloaded which results in a break that can be long when my connection is not great. Is there any good way to download my audio in chunks and flawlessly play it with Web Audio API.
(I have seen this question and response already, I'm wondering if there's a better/cleaner way of doing this without having to separately schedule the audio chunks)
I later figured out that probably the best way to achieve this is to use the getReader() function of the response body, this way I can read chunks, I also gave more information as to how I finally solved this question here.

Is it possible to create an audio file based on CSV-data and an existing audio file?

I am working on a project in JavaScript, and I need to do a fairly strange task. I am not sure how to achieve it. I have looked into the most popular libraries for audio, but it doesn't seem to be an easy way to just export a created file fast, without recording it in real-time. I might be wrong.
I am going to have some data as JSON or in CSV format with numbers in each row. That number corresponds to seconds elapsed. This data tells me when a certain audio file needs to be played. The audio file is just a 5-second long clip of beeps.
I need to generate a long audio file that is just silent, but where the audio clip plays when "instructed" by the data. So it could play at 10 seconds, 45 seconds, 267 seconds, etc.
The finished audio file could be over an hour long. I was hoping to create a system where I could just select an audio file and a data file from my computer, click a button, let it process, and then download the finished file.
I hope what I want to do is not unclear. Can I use the Web Audio API for this, or do I need a library? I am stuck at the first part of the process, namely what to use and how to "create" a file from nothing.
I think you could try MediaRecorder from MediaStream Recording API - it will let you create a recording function (something like this):
const stream = navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecorder = new MediaRecorder(stream);
// then you can get your number from JSON / CSV file and do next
mediaRecorder.start();
await sleep(YOUR_NUMBER_FROM_FILE);
mediaRecorder.stop();
The example above just creates audio that will be last concrete seconds.
You can load your existing files of audio and try it play in the background. I suppose MediaRecorder will record them too.
See MDN Web Docs about MediaRecorder
To summarize - Web Audio API and MediaStream Recording API will be enough for your case.
I hope this will help you in some ways.

convert audio source to a "use-once" blob

So I want to make it a little bit more difficult for users to directly download MP3 files from the server (just from going straight to the URL of the source). I've been looking around and, from what I've gathered, a good way to go about this is to convert an Audio object to a use-once Blob (similar to how YouTube does it).
As an example, something like this:
<!-- directly accessible, unobfuscated url -->
<audio src="www.mywebsite.com/media.mp3"></audio>
Would become:
<!-- visiting the link would lead to a 'your file was not found' page
and the original url is now obfuscated -->
<audio src="blob:http://www.mywebsite.com/6fc4f9d2-035a-4999-b330-96da04c0f6a8"></audio>
At the moment, this is how I'm doing it:
var url = "http://www.mywebsite.com/media.php"; // media.php points to an mp3 file
var audio = null; // just for simplicity sake - i'm not actually doing it like this
if(!audio){
audio = new Audio(url);
} else {
audio.pause();
audio.src = url;
}
Now I was looking at this answer (along with a couple others), but they all either involve using a file selected from an input or, as this one is, using the file as a Base64 string and converting that to a Blob, which I can't figure out how to do and imagine to be a somewhat heavy task to do on the client-side.
Essentially, all I need to do is convert the url to a Blob that can only be used once in that session (cannot be directly accessed in another tab - just that one time it's being played, for example).
NOTE: I Tagged PHP as this may also be a server-side issue, feel free to correct that if necessary.

Load large video file in HTML

Here is my problem : I want to play a large video file (3.6Gb) stored in a S3 bucket, but it seems the file is too big and the page crash after 30sec of loading.
This is my code to play the video :
var video = document.getElementById("video");
const mediaSource = new MediaSource();
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener('sourceopen', sourceOpen, { once: true });
function sourceOpen() {
URL.revokeObjectURL(video.src);
const sourceBuffer = mediaSource.addSourceBuffer('video/mp4; codecs="avc1.f40028"');
fetch('URL_TO_VIDEO_IN_S3')
.then(response => response.arrayBuffer())
.then(data => {
// Append the data into the new sourceBuffer.
sourceBuffer.appendBuffer(data);
})
.catch(error => {
});
}
I saw that blob URL could be a solution but it didn't work well with my URL.
Take my answer with a grain of salt as I am no expert. However, I am working on something very similar at the moment.
I suspect your issue is that you're attempting to load the entire resource (video file) into the browser at once. An object URL for a file size that exceeds a gigabyte is extremely large.
What you need to do is use the readable stream from the body of your fetch request to process the video file chunk-by-chunk. So as long as you aren't confined to working in the safari browser, you should be to use both the Readable and Writeable Stream classes natively in the browser.
These two classes allow you to form what's called a pipe. In this case, you are "piping" data from the readable stream in your fetch request to a writable stream that you create which is then used as the underlying source of data for your media source extension and it's respective source buffers.
A stream pipe is very special in that it exhibits what's called backpressure. You should definitely look this term up, and read about what it means. In this case, it means the browser will not request more data once it has enough to meet its needs for video playback, the exact amount it can hold at once is specified by you the programmer through something called a "highwater mark" (you should also read about this).
This allows you to control when and how much data the browser is requesting from your (on going) fetch request.
NOTE: When you use .then(response => response.arrayBuffer()) you are telling the browser to wait for the entire resource to come back and then turn the response into an array buffer.
OPTION 1
Use CloudFront to create RTMP distribution to these resources.
It will distribute your video in streaming way.
Create an RTMP distribution to speed up distribution of your streaming media files using Adobe Flash Media Server's RTMP protocol.
Please note that HTML5 does not support RTMP format by default (without flash).
Check here for options
JWPlayer supports RTMP playback using flash. SO Question
---
OPTION 2
Use Elastic Transcoder to create HLS video (.m3u8 format). Again same JWPlayer can handle it in ease.
Also it's mostly supported in native HTML5. Check compatibility with H.264

Dynamically create video (stream) with createObjectURL

I wonder if it is possible to create a html5 video on the fly. Some of you may noticed the new webrtc and its behavior with the video tag.
navigator.webkitGetUserMedia('video', gotStream, noStream);
function gotStream(stream) {
video.src = webkitURL.createObjectURL(stream);
}
what exactly is that "stream" in gotStream(stream) what is that "interface" looks like so i can generate one of my own? May it be by computing things or by just receiving data from server to display the video. Secound how do i get the data out of this "stream"? So i can read it from one users webcam to send it to my server and let it pass through the receiving user. Binary data transmission is no topic of my question, i already have this working.
I just need the data from the "stream" from one user and reconstruct that "stream" on the target user who wanna see user ones webcam.
Any further information on "where to get these infos by my self" (API Docu sort of) would be also very helpful, cuz i cant find any.
I am aware of the PeerConnection stuff, so no need to mention it here. Cuz beside that webcam stuff i would love to pipe dynamically generated videos from my server to the client or make some sort of video transmitting over dynamic changeable bandwidth with ffmpeg etc. but for this i need to pipe that data to that video element
You may want to look at Whammy: http://antimatter15.com/wp/2012/08/whammy-a-real-time-javascript-webm-encoder/.
For now, you can periodically copy a video element screen to a canvas, then save that canvas to build a video. Whammy ties together webp images generated from a canvas into a webm file, taking advantage of the similarities of the webp (image) and webm (video) format.
You could generate other images and stitch them together in the same manner. Note that this does not support audio.

Categories