progressive load and play video from base64 pieces - html

I have many pieces of a video in base64.
Just that I want is to play the video progressively as I receive them.
var fileInput = document.querySelector('input#theInputFile');//multiple
fileInput.addEventListener('change', function(e) {
var files = fileInput.files;
for (var i = 0; i < files.length; i++) {
var file = fileInput.files[i]
fileLoaded(file, 0, 102400, file.size);
};
e.preventDefault();
});
videoA=[];
function fileLoaded(file, ini, end, size) {
if (end>size){end=size}
var reader = new FileReader();
var fr = new FileReader();
fr.onloadend = function(e) {
if (e.target.readyState == FileReader.DONE) {
var piece = e.target.result;
display(piece.replace('data:video/mp4;base64,', ''));
}
};
var blob = file.slice(ini, end, file.type);
fr.readAsDataURL(blob);
var init = end;
var endt = init+end;
if (end<size){
fileLoaded(file, init, end, size);
}
}
Trying to display the video by chunks:
var a=0;
function display(vid, ini, end) {
videoA.push(vid);
$('#video').attr('src','data:video/mp4;base64,'+videoA[a]);
a++;
}
I know this is not the way but I`m trying to search and any response adjust to that I'm searching.
Even I'm not sure if it is possible.
Thanks!
EDIT
I've tried to play the chunks one by one and the first one is played well but the rest of them give the error:
"Uncaught (in promise) DOMException: Failed to load because no supported source was found".
If I could make the chunks to base64 correctly it's enough for me

Ok, the solution is to solve the creation of base64 pieces from the original uploaded file in the browser that can be played by an html5 player
So I've put another question asking for that.
Chunk video mp4 file into base64 pieces with javascript on browser

Related

getUserMedia and mediarecorder in html

I record audio via getUserMedia and mediarecorder:
...
navigator.mediaDevices.getUserMedia(constraints).then(mediaStream => {
try {
const mediaRecorder = new MediaRecorder(mediaStream);
mediaRecorder.ondataavailable = vm.mediaDataAvailable;
mediaRecorder.start(1000);
...
When I receive the chucks in the callback, I send them to a web api via websockets, which simply writes the parts one after another to a file:
mediaDataAvailable(e) {
if (!event.data || event.data.size === 0)
{
return;
}
vm.websocket.SendBlob(e.data);
...
The file, which is created on the webserver side in the webapi (lets call it "server.webm"), does not work correct. More exactly: It plays the first n seconds (n is the time I chose for the start command), the it stops. This means, the first chunk is transferred correctly, but it seams that adding the 2nd, 3rd, ... chuck together to a file does not work. If I push the chuncks in the web page on an array and the to a file, the resulting file (lets call it "client.webm") is working the whole recording duration.
Creating file on web client side:
mediaDataAvailable(e) {
if (!event.data || event.data.size === 0)
{
return;
}
vm.chuncks.push(e.data);
...
stopCapturing() {
var blob = new Blob(this.chuncks, {type: 'audio/webm'});
var url = window.URL.createObjectURL(blob);
var a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'client.webm';
document.body.appendChild(a);
a.click();
I compared the files client.webm and server.webm. They are quite similar, but there are certain parts in the server.webm which are not in the client.webm.
Anybody any ideas? Server code looks like the following:
private async Task Echo( HttpContext con, WebSocket webSocket)
{
System.IO.BinaryWriter Writer = new System.IO.BinaryWriter(System.IO.File.OpenWrite(#"server.webm"));
var buffer = new byte[1024 * 4];
WebSocketReceiveResult result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
while (!result.CloseStatus.HasValue)
{
Writer.Write(buffer);
Writer.Flush();
await webSocket.SendAsync(new ArraySegment<byte>(buffer, 0, result.Count), result.MessageType, result.EndOfMessage, CancellationToken.None);
result = await webSocket.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
}
await webSocket.CloseAsync(result.CloseStatus.Value, result.CloseStatusDescription, CancellationToken.None);
Writer.Close();
}
resolved, I write all bytes of the reserved byte array to file in server code, not the count of received bytes.

Is possible to reuse DOMString returned from HTMLCanvasElement.toDataURL() or canvas.toBlob()?

I am setting up an image Cropper, it will give me width and height,X and Y of cropped details. Using that I am creating a preview image (using canvas) but is it possible to store that data returned from HTMLCanvasElement.toDataURL() or canvas.toBlob() and reuse in other devices and browsers?
Refer below link (it uses canvas.toBlob() method)
https://codesandbox.io/s/72py4jlll6
You can try use this lines of code:
if (!HTMLCanvasElement.prototype.toBlob) {
Object.defineProperty(HTMLCanvasElement.prototype, 'toBlob', {
value: function (callback, type, quality) {
var binStr = atob( this.toDataURL(type, quality).split(',')[1] ),
len = binStr.length,
arr = new Uint8Array(len);
for (var i=0; i<len; i++ ) {
arr[i] = binStr.charCodeAt(i);
}
callback( new Blob( [arr], {type: type || 'image/png'} ) );
}
});
}
Just change to your code.
Please LMK soon.
Ypu can convert Blob to base64 string,
and save it on server side.
So you can serve this media later to different user/browser.
The way to do it is:
let reader = new FileReader();
reader.readAsDataURL(blob); // converts the blob to base64 and calls onload
reader.onload = function() {
data = reader.result; // data url as base 64 encoded string.
};
Decoding this string will get you the binary PNG data.

HTML5 web audio controls

I have music play example http://www.smartjava.org/examples/webaudio/example3.html
And i need to show html5 audio player (with controls) for this song. How i can do it?
Javascript code from example below:
// create the audio context (chrome only for now)
// create the audio context (chrome only for now)
if (! window.AudioContext) {
if (! window.webkitAudioContext) {
alert('no audiocontext found');
}
window.AudioContext = window.webkitAudioContext;
}
var context = new AudioContext();
var audioBuffer;
var sourceNode;
var analyser;
var javascriptNode;
// get the context from the canvas to draw on
var ctx = $("#canvas").get()[0].getContext("2d");
// create a gradient for the fill. Note the strange
// offset, since the gradient is calculated based on
// the canvas, not the specific element we draw
var gradient = ctx.createLinearGradient(0,0,0,300);
gradient.addColorStop(1,'#000000');
gradient.addColorStop(0.75,'#ff0000');
gradient.addColorStop(0.25,'#ffff00');
gradient.addColorStop(0,'#ffffff');
// load the sound
setupAudioNodes();
loadSound("http://www.audiotreasure.com/mp3/Bengali/04_john/04_john_04.mp3");
function setupAudioNodes() {
// setup a javascript node
javascriptNode = context.createScriptProcessor(2048, 1, 1);
// connect to destination, else it isn't called
javascriptNode.connect(context.destination);
// setup a analyzer
analyser = context.createAnalyser();
analyser.smoothingTimeConstant = 0.3;
analyser.fftSize = 512;
// create a buffer source node
sourceNode = context.createBufferSource();
sourceNode.connect(analyser);
analyser.connect(javascriptNode);
sourceNode.connect(context.destination);
}
// load the specified sound
function loadSound(url) {
var request = new XMLHttpRequest();
request.open('GET', url, true);
request.responseType = 'arraybuffer';
// When loaded decode the data
request.onload = function() {
// decode the data
context.decodeAudioData(request.response, function(buffer) {
// when the audio is decoded play the sound
playSound(buffer);
}, onError);
}
request.send();
}
function playSound(buffer) {
sourceNode.buffer = buffer;
sourceNode.start(0);
}
// log if an error occurs
function onError(e) {
console.log(e);
}
// when the javascript node is called
// we use information from the analyzer node
// to draw the volume
javascriptNode.onaudioprocess = function() {
// get the average for the first channel
var array = new Uint8Array(analyser.frequencyBinCount);
analyser.getByteFrequencyData(array);
// clear the current state
ctx.clearRect(0, 0, 1000, 325);
// set the fill style
ctx.fillStyle=gradient;
drawSpectrum(array);
}
function drawSpectrum(array) {
for ( var i = 0; i < (array.length); i++ ){
var value = array[i];
ctx.fillRect(i*5,325-value,3,325);
// console.log([i,value])
}
};
I think what you want is to use an audio tag for your source and use createMediaElementSource to pass the audio to webaudio for visualization.
Beware that createMediaElementSource checks for CORS access so you must have appropriate cross-origin access for this to work. (It looks like your audio source doesn't return the appropriate access headers for this to work.)

HTML5 FileReader alternative

I need some help with HTML5. I have a script that loops through all the uploaded files and gets each file details. Currently I am using HTML5 techniques that include FileReader. The FileReader function only works in Chrome and Firefox, so I am looking for an alternative which will work in all of the other browsers.
I saw the Stack Overflow question Flash alternative for FileReader HTML 5 API, but I wasn't able to figure how to use this Flash thing, and aren't there any other solutions so I can loop through all of the uploaded files and get each file details (which will work in Safari and Internet Explorer)?
Ended up not using FileReader at all, instead I looped through event.files and got each file by files[i] and sent an AJAX request by XHR with a FormData object (worked for me because I decided I don't need to get the file data):
var xhrPool = {};
var dt = e.dataTransfer;
var files = (e.files || dt.files);
for (var i = 0; i < files.length; i++) {
var file = files[i];
// more code...
xhrPool[i] = getXMLHttpRequest();
xhrPool[i].upload.onprogress = uploadProgress;
initXHRRequest(xhrPool[i], i, file);
data = initFormData(i, file);
xhrPool[i].send(data);
}
function initFormData(uploaded, file) {
var data = new FormData();
data.append(uploaded, file);
// parameters...
return data;
}
function uploadProgress() {
// code..
}
function initXHRRequest(xhr, uploaded, file) {
// code... onreadystatechange...
xhr.open("POST", "ajax/upload.php");
xhr.setRequestHeader("X-File-Name", file.name);
}
function getXMLHttpRequest()
{
if (window.XMLHttpRequest) {
return new XMLHttpRequest();
}
else {
try {
return new ActiveXObject("MSXML2.XMLHTTP.3.0");
}
catch(ex) {
return null;
}
}
}
Safari was the first one to actually implement the HTML5 file API, and there are several demos. Andrea Giammarchi has a nice description on his blog. There are several frameworks to handle this as well which also have fallbacks for Internet Explorer. Fancyupload is one that comes to mind.

how to send binary strings with ajax to php - including html5 file api - blob slice

what i'm trying to do is uploading a file, slice it into 3 parts and give each one to different databases, so i
can excess it later by connecting all parts.
the only trouble i have is sending the binary-string to php so i can write it to my databases.
i have no clew what setting the content-type header to etc. althrough lots of other people seem to have a similar problem, i couldn't find any satisfying solution.
any help?
CODE/
index.php
<input type="file" id="file" name="file" onchange="filesProcess(this.files)" /><br/>
javascript
function filesProcess(files) {
for (i = 0; i<files.length;i++){
var file = files[i];
var users = 3;
var abschnitt = file.size/users;
var start = 0;
for (var z = 1; z<=users; z++){
sliceFiles(z, users, start, file, abschnitt);
start = start + abschnitt + 1;
}
}
}
function sliceFiles(z, users, start, file, abschnitt) {
var reader = new FileReader();
var blob = file.slice(start, abschnitt);
reader.readAsBinaryString(blob);
reader.onloadend = function(evt) {
var contentfile = evt.target.result;
upload(z, users, contentfile);
}
}
function upload(z, users, contentfile) {
xhr = new XMLHttpRequest();
xhr.onreadystatechange=function(){
if (xhr.readyState==4 && xhr.status==200)
{
$("#output").html(xhr.responseText);
}
}
if (z == 1){
xhr.open("POST","upload_1.php",true);
}
if (z == 2){
xhr.open("POST","upload_2.php",true);
}
if (z == 3){
xhr.open("POST","upload_3.php",true);
}
xhr.setRequestHeader("Content-type", "multipart/form-data");
xhr.send("inhalt="+contentfile);
}
Are you trying to send the blob as a string? Anyway, maybe the link below is helpful. It's about a chunked file uploader for Google Gears, I've implemented a similar solution a while back when Gears was still hot. The new JS File API implementation isn't that different, so I reckon you could modify the solution to fit your needs (and for use with the new JS File Api).
http://perplexed.co.uk/549_gears_multiple_file_upload.htm