Media Source Extension issue on change for new segments - javascript

there
I have two videos segments array
video1 = ['v1_1.ts','v1_2.ts','v1_3.ts','v1_4.ts',...]
video2 = ['v2_1.ts','v2_2.ts','v2_3.ts','v2_4.ts',...]
MSE is working perfect with playing video1 segments, but when I try to play video segments 2 nothing happened
I can't even restart playing video1 segments
Can anyone explain, how to start playing new video segments in Media Source Extension
<html>
<head>
<title>Basic Transmuxer Test</title>
</head>
<body>
<div><button onclick="play1()">Restart video</button>
<video controls width="80%"></video>
<script src="https://github.com/videojs/mux.js/releases/latest/download/mux.js"></script>
<script>
// Create array of TS files to play
segments = [
"segment_1.ts",
"segment_2.ts",
"segment_3.ts",
"segment_4.ts"
];
// Replace this value with your files codec info
mime = 'video/mp4; codecs="mp4a.40.2,avc1.64001f"';
let mediaSource = new MediaSource();
mediaSource.addEventListener('error', function(err) {
throw new Error("MSE: " + err.message);
});
let sourceBuffer = null;
let transmuxer = new muxjs.mp4.Transmuxer();
video = document.querySelector('video');
video.src = URL.createObjectURL(mediaSource);
mediaSource.addEventListener("sourceopen", appendFirstSegment);
function play1(){
sourceBuffer.abort();
segments = [
"segment_0.ts",
"segment_1.ts",
"segment_2.ts",
"segment_3.ts",
"segment_4.ts",
"segment_5.ts",
"segment_6.ts",
"segment_7.ts",
"segment_8.ts",
"segment_9.ts"
];
appendFirstSegment()
}
function appendFirstSegment(){
if (segments.length == 0){
return;
}
console.log('appendFirstSegment')
if(!sourceBuffer){
sourceBuffer = mediaSource.addSourceBuffer(mime);
sourceBuffer.mode = 'sequence';
}
//mediaSource.duration = 0;
sourceBuffer.addEventListener('updateend', appendNextSegment,false);
transmuxer.off('data');
transmuxer.on('data', (segment) => {
let data = new Uint8Array(segment.initSegment.byteLength + segment.data.byteLength);
data.set(segment.initSegment, 0);
data.set(segment.data, segment.initSegment.byteLength);
console.log(muxjs.mp4.tools.inspect(data));
sourceBuffer.appendBuffer(data);
})
fetch(segments.shift()).then((response)=>{
return response.arrayBuffer();
}).then((response)=>{
transmuxer.push(new Uint8Array(response));
transmuxer.flush();
})
}
function appendNextSegment(){
// reset the 'data' event listener to just append (moof/mdat) boxes to the Source Buffer
transmuxer.off('data');
transmuxer.on('data', (segment) =>{
sourceBuffer.appendBuffer(new Uint8Array(segment.data));
})
if (segments.length == 0){
// notify MSE that we have no more segments to append.
//mediaSource.endOfStream();
}
if(segments.length>0){
fetch(segments.shift()).then((response)=>{
return response.arrayBuffer();
}).then((response)=>{
transmuxer.push(new Uint8Array(response));
transmuxer.flush();
})
}
}
</script>
</body>
</html>

Related

Choosing audio format when saving data locally on a web app

I have a web app getting some audio recording input from the user.
And there is a button to save it locally as an audio file.
The resulting file I am getting is of ogg-opus format. Concretely when I use the file command I get this in the terminal:
MyMac$ file Clip.wav
Clip.wav: Ogg data, Opus audio,
MyMac$
I can check that the recording is all right using VLC.
On the other hand I can't play the file with afplay as is normally possible with an mp3, m4a or wav file.
MyMac$ afplay Clip.wav
Error: AudioFileOpen failed ('typ?')
MyMac$
Here follows my relevant code:
if (navigator.mediaDevices.getUserMedia) {
// getUserMedia is supported.
const constraints = { audio: true };
let chunks = [];
let onSuccess = function(stream) {
const mediaRecorder = new MediaRecorder(stream);
visualize(stream);
........
mediaRecorder.onstop = function(e) {
........
audio.setAttribute('controls', '');
........
audio.controls = true;
const blob = new Blob(chunks, { 'type' : 'audio/wav;codecs=0' });
chunks = [];
........
upload.addEventListener("click",
function(event) {loadToServer(blob)})
........
}
mediaRecorder.ondataavailable = function(e) {
chunks.push(e.data);
}
}
let onError = function(err) {
console.log('The following error occured: ' + err);
}
navigator.mediaDevices.getUserMedia(constraints).then(onSuccess, onError);
} else {
console.log('getUserMedia not supported on your browser!');
}
I would like to know how to change my code in order to generate a proper wav file or even mp3.
Note:
I have made trials modifying this line of code:
const blob = new Blob(chunks, { 'type' : 'audio/wav;codecs=0' });
in various ways, but is has no effect at all.
In order to specify the mimeType of your recording you need to tell the MediaRecorder which mimeType you prefer before it starts the recording.
- const mediaRecorder = new MediaRecorder(stream);
+ const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/wav' });
Unfortunately audio/wav is not supported by any browser. You will get an error when trying the snippet above.
Since I needed wav recordings as well I built a library which is meant to add this functionality. It's called extendable-media-recorder because it could be extended with any other (audio) codec you like.
If you don't want to use a third party library and keep the browser using the codec it likes best you can save your file like this in order to get a valid file with the correct suffix.
- const blob = new Blob(chunks, { 'type' : 'audio/wav;codecs=0' });
+ const blob = new Blob(chunks, { 'type' : mediaRecorder.mimeType });
The suffix would then be the portion of the type after the slash and before a possible semicolon.
Here is an example of a full HTML document that uses jspm to load extendable-media-recorder without a bundler.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
</head>
<body>
<button id="start" disabled>start</button>
<button id="stop" disabled>stop</button>
<script type="module">
import { MediaRecorder, register } from 'https://jspm.dev/extendable-media-recorder';
import { connect } from 'https://jspm.dev/extendable-media-recorder-wav-encoder';
const $start = document.getElementById('start');
const $stop = document.getElementById('stop');
await register(await connect());
const chunks = [];
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
const mediaRecoder = new MediaRecorder(stream, { mimeType: 'audio/wav' });
mediaRecoder.addEventListener('dataavailable', ({ data }) => {
chunks.push(data);
});
mediaRecoder.addEventListener('stop', ({ data }) => {
const blob = new Blob(chunks, { type : mediaRecoder.mimeType });
console.log(blob);
});
$start.addEventListener('click', () => {
mediaRecoder.start();
$stop.addEventListener('click', () => {
$stop.disabled = true;
mediaRecoder.stop();
});
$start.disabled = true;
$stop.disabled = false;
});
$start.disabled = false;
</script>
</body>
</html>

Echo $row database value inside a javascript

How can i display database value $row in javascript?
At line 3 const source = 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8'; I want the link/url get from database. base on url id domain.com/video.php?id=12
I already try like this but doesn't work const source = '<?php echo $row["video_url"]; ?>'
Here is the code
<script>
document.addEventListener('DOMContentLoaded', () => {
const source = 'https://bitdash-a.akamaihd.net/content/sintel/hls/playlist.m3u8';
const video = document.querySelector('video');
// For more options see: https://github.com/sampotts/plyr/#options
// captions.update is required for captions to work with hls.js
const player = new Plyr(video, {captions: {active: true, update: true, language: 'en'}});
if (!Hls.isSupported()) {
video.src = source;
} else {
// For more Hls.js options, see https://github.com/dailymotion/hls.js
const hls = new Hls();
hls.loadSource(source);
hls.attachMedia(video);
window.hls = hls;
// Handle changing captions
player.on('languagechange', () => {
// Caption support is still flaky. See: https://github.com/sampotts/plyr/issues/994
setTimeout(() => hls.subtitleTrack = player.currentTrack, 50);
});
}
// Expose player so it can be used from the console
window.player = player;
});
</script>
EDITED: The output for this script is empty const source = ''

how should I go by making a audio file converter in react

I am trying to make an audio file converter that lets a user submit a file. Then uses JavaScripts Web Audio API to convert the pitch and stretch the file. I have gotten as far as uploading the file, use file reader to onload a function that stretches and converts the pitch. Now I am trying to export that file with the changes and I can right now only download the original file but not with the changes. I dont know how to assign file = buffer because it's from another class. How should I got by making this happen?
convertFile () {
var fileInput = document.getElementById('audio-file')
var ctx = new AudioContext()
var convertFiles = document.getElementById('convert_button')
//load audio file listener
convertFiles.addEventListener("click", function() {
if (fileInput.files[0] == undefined) {
console.log("no file found")
return false
}
var reader1 = new FileReader()
reader1.onload = function(ev) {
ctx.decodeAudioData(ev.target.result). then(function(buffer){
var soundSource = ctx.createBufferSource()
soundSource.buffer = buffer
// create the stretch
soundSource.playbackRate.linearRampToValueAtTime(0.0185, ctx.currentTime)
//connect source
soundSource.connect(ctx.destination)
// convert pitch
var pitchChange = ctx.createBiquadFilter()
pitchChange.type = 'highpass'
pitchChange.frequency.value = 432
pitchChange.connect(ctx.destination)
})
}
reader1.readAsArrayBuffer(fileInput.files[0])
})
let file = fileInput.files[0]
let url = URL.createObjectURL(file)
let link = document.createElement('a')
link.href = url
link.download = file.name
link.click()
link = null
URL.revokeObjectURL(url)
}
render() {
return (
<div className="sec2">
<input type="file" id="audio-file" accept="audio/mpeg, audio/ogg, audio/*" name="file" onChange={this.uploadFile} />
<button type="button" id="convert_button" onClick={this.convertFile}>Convert to 432Hz</button>
<download onClick={this.downloadFile}>Download File</download>
</div>
)
}
}
export default ConverterSec2
I started looking into this... I fixed a couple issues such as the audio file being loaded twice. However this is work in progress answer... I haven't figure out the saving part yet.
class ConverterSec2 extends React.Component {
uploadFile = ({ target: { files } }) => {
console.log(files[0])
let data = new FormData()
data.append('file', files[0])
}
convertFile () {
var fileInput = document.getElementById('audio-file')
var ctx = new AudioContext()
var convertFiles = document.getElementById('convert_button')
//load audio file listener
if (fileInput.files[0] == undefined) {
console.log("no file found")
return false
}
var soundSource = ctx.createBufferSource();
var reader1 = new FileReader()
reader1.onload = function(ev) {
ctx.decodeAudioData(ev.target.result).then(function(buffer){
soundSource.buffer = buffer
// create the stretch
soundSource.playbackRate.linearRampToValueAtTime(0.0185, ctx.currentTime)
//connect source
soundSource.connect(ctx.destination)
// convert pitch
var pitchChange = ctx.createBiquadFilter()
pitchChange.type = 'highpass'
pitchChange.frequency.value = 432
pitchChange.connect(ctx.destination)
})
}
reader1.readAsArrayBuffer(fileInput.files[0]);
}
downloadFile() {
let fileInput = document.getElementById('audio-file')
let file = fileInput.files[0]
let url = URL.createObjectURL(file)
let link = document.createElement('a')
link.href = url
link.download = file.name
link.click()
link = null
URL.revokeObjectURL(url)
}
render() {
return (
<div className="sec2">
<input type="file" id="audio-file" accept="audio/mpeg, audio/ogg, audio/*" name="file" onChange={this.uploadFile} />
<button type="button" id="convert_button" onClick={this.convertFile}>Convert to 432Hz</button>
<button onClick={this.downloadFile}>Download File</button>
</div>
)
}
}
Live Demo

download and play stream audio in angular 8

i need to play sound with user click on the preview icon .
this is my html code :
<audio controls>
<source [src]="fileSource" type="audio/mp3">
</audio>
this this is ts code :
fileSource: any;
ngOnInit(): void {
if (typeof this.data.src === 'number') {
this.getImageFromService();
}
}
createImageFromBlob(image: Blob): void {
const reader = new FileReader();
reader.addEventListener('load', () => {
this.fileSource = reader.result;
}, false);
if (image) {
reader.readAsDataURL(image);
}
}
getImageFromService(): void {
this.isLoading = true;
this.postFileService.downloadFile(this.data.src).subscribe(data => {
this.createImageFromBlob(data);
this.isLoading = false;
}, error => {
this.isLoading = false;
console.log(error);
});
}
and this is my service :
downloadFile(id: number): Observable<Blob> {
const URL = `${this.appConfig.apiEndpoint + '/PostFileContent/DownloadFile/' + id}`;
return this.http.get(URL, { responseType: 'blob' });
}
now my prolem is this :
i need to when click the preview icon T open the modal dialog box and play audio .
when i click on the preview icon the file is downloaded but it not play .
whats the problem ? how can i solve this ???
Following code will work for playing audio automatically file which was retrieved from backend(node.js).
angular.html
<audio controls>
<source type="audio/mpeg" [src]="fileSource" >
</audio>
angualr.ts
// mention your backend url directly here like below
fileSource:any = 'http://localhost:1234/getAudioFile';
node-backend-code
app.use('/getAudioFile',function(req,res,next){
// i stored sample mp3 file in my local directory
var filePath = path1.join(__dirname, './sample.mp3');
var stat = fileSystem.statSync(filePath);
res.writeHead(200, {
'Content-Type': 'audio/mpeg',
'Content-Length': stat.size
});
var readStream = fileSystem.createReadStream(filePath);
// We replaced all the event handlers with a simple call to readStream.pipe()
readStream.pipe(res);
// res.send("this is audio ");
next();
});
Note:: Make sure that you get directly audio file from backend(irrespective of node or java).

Uploading an audio file obtained via getUserMedia() and Javascript to a server using PHP

I have pieced together a Javascript audio recorder that grabs the user microphone via getUserMedia and records and outputs a .OGG file for download. Note this only works in Firefox, which is fine for me.
Rather than provide a download link I want the file to be uploaded to the server via PHP as soon as it stops recording. I'm not sure how I should be going about doing that. I have tried using a form to grab it from $_FILES but I can't figure out how to pre populate the form with the BLOB to submit.
Here is what I have so far. Any input on how to move this along to a server via PHP would be appreciated!
<html>
<head>
</head>
<body>
<div id="container">
<audio controls autoplay></audio>
<a id="downloadLink" download="mediarecorder.ogg" name="mediarecorder.ogg" href></a>
<p id="data"></p>
<script >
navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
var constraints = {audio: true};
var audioElement = document.querySelector('audio');
var dataElement = document.querySelector('#data');
var downloadLink = document.querySelector('a#downloadLink');
function errorCallback(error){
console.log("navigator.getUserMedia error: ", error);
}
var count = 0;
function startRecording(stream) {
log('Starting...');
mediaRecorder = new MediaRecorder(stream);
mediaRecorder.onerror = function(e){
log('Error: ' + e);
};
mediaRecorder.onstart = function(e){
log('Started');
};
mediaRecorder.onstop = function(e){
log('Stopped');
};
mediaRecorder.onwarning = function(e){
log('Warning: ' + e);
};
// parameter is number of milliseconds of data to return in a single Blob
mediaRecorder.start();
window.setTimeout(function(){
mediaRecorder.stop();
}, 2400000);
}
window.onload = function(){
if (typeof MediaRecorder === 'undefined' || !navigator.getUserMedia) {
alert('Sorry! This demo requires Firefox Nightly.');
} else {
window.onkeydown = function(e){
if ( e.keyCode == 82 ) { //R pressed
navigator.getUserMedia(constraints, startRecording, errorCallback);
} else if ( e.keyCode == 83 ) { // S pressed
mediaRecorder.stop();
mediaRecorder.ondataavailable = function(e) {
log('Data available...');
count++;
if (count > 1) {
return;
}
console.log(e);
audioElement.src = window.URL.createObjectURL(e.data);
downloadLink.href = window.URL.createObjectURL(e.data); //Audio BLOB
downloadLink.innerHTML = "Download ogg audio file";
};
}
}
}
};
function log(message){
dataElement.innerHTML = message + '<br>' + dataElement.innerHTML ;
}
</script>
</div>
</body>
</html>
For security reasons in most browsers it is not allowed to pre fill an html upload element. Is the ogg file stored locally (on the client). If it is stored on the webserver an option could be to post the (public available) url to a php script and open it in by using file_get_contents.

Categories

Resources