Cutting video in JavaScript - javascript

I have a video element like:
<video id="video" width="320" height="240" autoplay controls muted></video><br/>
The stream data are pushed into an array:
let blobs_recorded = [];
media_recorder = new MediaRecorder(camera_stream, { mimeType: 'video/webm' });
media_recorder.addEventListener('dataavailable', function(e) {
blobs_recorded.push(e.data);}
All is running fine and I can record a full video without problem. Well I want to create an new video from this full recorded video and only want to get the last three seconds of this vid until end. I tried to manipulate the Blobs but video is then black. I found out if I put the the first blob to the new video then I can see this video, but I got the metadata of the full big video in the small video. Any idea how I can solve it smart?
Greetings.

Related

Plyr audio player muted for the first second of audio

I am using Plyr audio player for my Rails app, along with Simulus.js.
I dynamically add audio source when the user clicks on different audio buttons. Then I launch the audio player with the .play() method.
However, the beginning of the track can't be heard. You can try it out on this URL, by taping the first audio player. If you put back the audio cursor to the beginning, then you can hear the very beginning of the track.
Here is my HTML:
<audio class="player" controls data-dicteeModule-target="player">
<source class="player-source" src="<%= dictee_modules.first.audio_url %>" type="audio/mp3" />
</audio>
Here is how I initialize the player:
initialize() {
const players = document.getElementsByClassName('player');
var player = [];
Array.from(players).forEach(function (ele, i) {
player[i] = new Plyr(ele, {
controls: ['progress']
});
});
}
Here is my Stimulus onclick action:
var player = this.playerTarget;
var source = audio.getAttribute("data-audio-source");
var audioSource = player.getElementsByClassName("player-source")[0];
audioSource.src = source;
player.load();
player.addEventListener('canplay', (event) => {
player.play();
});
Any idea why the very beginning of the track is not heard?
Thanks.
This happens to me too on various websites that need to use audio after no audio was used for a while, even on YouTube. I'm using Chrome 104.0.5112.81 on Windows 10.
It's likely a driver issue you can't do much about (assuming YouTube would fix it if they could). It looks like Windows or Chrome ends up dimming the sound way too quickly, and takes too long turning it back on.
Unfortunately I couldn't find anything on Google yet. It seems hard to make Google understand this query, it only returned results about audio preventing PC sleep mode (or other unrelated common issues), no matter how I phrased it. Could also indicate it's just a very obscure issue with one or a few particular drivers.

Get audio from HTML5 video

I have been trying to figure out this for a week.
I have two completely different video tags with their respective audio. I also have one audio tag. At first, both muted attribute is set for both video tags. When I want to get video1 audio, I would like to get it audio source and assign it to the audio tag. Also do the same for video2.
Is this possible with Javascript? I have tried Web audio API but I'm lost. Please help.
I am not sure I get what you want.
To copy the video's audio stream to an audio element, you could simply set the src of the <audio> element to the video's src :
<audio src="http://media.w3.org/2010/05/sintel/trailer.mp4" controls autoplay></audio>
Then you could try to sync it with your video tag's currentTime, or sync the video's currentTime with the <audio>'s one and unmute the video, while the audio would be muted, but I'm not sure you'll get awesome results. Also, it won't be a surprise if some browsers will load the video twice in the same time.
Now, what can you do with the WebAudioAPI :
It would be really hard to make your audio streams into the audio tags, live and in a cross-browser way.
If you don't need this however, it's pretty easy to create some MediaSource from video elements thanks to the createMediaElementSource() method.
Once these MediaSource objects are created, your original media will be disconnected from the normal output. You need to keep their muted attribute unset or set to false in order to hear it as a MediaSource object.
Here is a simple example that will allow you to mute/unmute a video source, from the WebAudioAPI only :
var vid = document.getElementById('vid');
var audioCtx = new AudioContext();
var gainNode = audioCtx.createGain();
var v1_src = audioCtx.createMediaElementSource(vid);
gainNode.connect(audioCtx.destination);
btn_1.onclick = function() {
var playing = this.textContent.indexOf('listen') < 0;
if (playing) {
v1_src.disconnect();
this.textContent = this.textContent.replace('mute', 'listen');
} else {
v1_src.connect(gainNode);
this.textContent = this.textContent.replace('listen', 'mute');
}
}
video { height: 120px;}
<button id="btn_1">listen</button><br>
<video id="vid" crossOrigin='anonymous' src="http://vjs.zencdn.net/v/oceans.mp4" loop autoplay></video>
Note that the media passed to this method must come from a safe domain request (see CORS).

Changing html5 video source with preloading

I'm setting up a video portfolio site to showcase different concepts for software devs, and there are often multiple versions of the same video.
I wrote the following javascript to change videos and it works fine locally, the problem is that once its hosted changing videos breaks the video player. I'm guessing the cause is because the new video is not loaded. Any ideas?
function switcher(wrapper, e, source, container, video){
//get current version and turn off its style
var off = document.getElementById(wrapper).getElementsByClassName("versionActive")[0];
off.className = "version";
//turn on the new button
e.className = "versionActive";
var videoSource = document.getElementById(source);
var videoContainer = document.getElementById(container);
lastPlayingVideo.currentTime = 0;
lastPlayingVideo.pause();
lastPlayingVideo = videoContainer;
videoSource.setAttribute('src', video);
videoContainer.load();
videoContainer.play();
}
The html for the video player looks like this:
<video id="container1" controls="" loop="" preload="auto" width="1280" height="720">
<source id="video1" src="videos/Reminder.mp4" type="video/mp4">
</video>
Try :
videoContainer.addEventListener('canplay', function() {
videoContainer.play();
videoContainer.removeEventListener('canplay');
});
videoSource.setAttribute('src', video);
videoContainer.load();
canplay is fired when the browser supposes you have received enough of the file and you can continue playing it considering your connection speed.

HTML5 video source changing

I have a video tag like this. All this videos have to play dynamically one after other
I tried writing some javascript functions in eventlistner "progress" of the video, but not working.How to play these videos automatically?anybody please suggest any codes in javascript or jquery
<div id="divVid">
<video id="video1" width="320" height="240" autoplay >
<source src="vid_future technology_n.mp4#t=20,50" >
Your browser does not support the video tag.
</video>
</div>
JS Code (Updated from comment section)
document.getElementById("video1")
.addEventListener("progress",
function () {
var i = 0;
var vid = document.getElementById("video1");
if (vid.paused) {
if (vid.currentSrc == myvids[i]) {
vid.currentSrc = myvids[i + 1]; } i = i + 1;
}
});
The set of <source> elements provide alternative formats for the video for different devices, not a playlist.
If you want to have a playlist, then listen for an ended event and change the src with JavaScript.
In response to edits to the question:
No, really change the src. You are trying to change the currentSource which is defined as being readonly
I said ended. Don't touch progress, you what to play the next video when the last one is finished, not when a tiny chunk of it has played
The list of <source> elements still isn't a playlist. Don't try to use them as such. Keep the list of videos somewhere else (e.g. a JS array).

Dynamically using the first frame as poster in HTML5 video?

I'm wondering if there's any straightforward way to achieve this effect, without needing backend code to extract a frame, save it as a jpg and database it somewhere.
An effect whereby the first frame of the video just shows up as the poster when the video loads would be so helpful (it would only work if the browser can play back the video obviously, which might be a little different from how poster traditionally works, but that is not a concern.
Did you try the following?
just append time in seconds #t={seconds} to source URL:
<video controls width="360">
<source src="https://test-videos.co.uk/vids/bigbuckbunny/mp4/h264/1080/Big_Buck_Bunny_1080_10s_1MB.mp4#t=0.1" type="video/mp4" />
</video>
I have chosen a fraction of second (0.1) to keep number of frames small, because I have the suspect that if you put 1 second, it would "preload" the first 1 second of video (i.e. 24 frames or more ....). Just in case ...
Works fine on Chrome and Firefox on desktop :)
Works not on Android mobile, though :(
I did not test on iOS, iPhone, IE yet ??
Edit May 2021:
I realized that many modern browsers now show automatically a poster of first frame.
Seems like they heard us :-)
To make it simple you can just add preload="metadata" to your video tag and the second of the first frame #t=0.5 to your video source:
<video width="400" controls="controls" preload="metadata">
<source src="https://www.w3schools.com/html/mov_bbb.mp4#t=0.5" type="video/mp4">
</video>
Best of luck!
There is a Popcorn.js plugin called Popcorn.capture which will allow you to create posters from any frame of your HTML5 video.
There is a limitation that is imposed by the browser that prohibits reading pixel data of resources requested across domains (using the canvas API to record the current value of a frame). The source video must be hosted on the same domain as the script and html page that is requesting it for this approach to work.
The code to create poster using this plugin is quite simple:
// This block of code must be run _after_ the DOM is ready
// This will capture the frame at the 10th second and create a poster
var video = Popcorn( "#video-id" );
// Once the video has loaded into memory, we can capture the poster
video.listen( "canplayall", function() {
this.currentTime( 10 ).capture();
});
I recently did this for a recent project that works on desktop and mobile. The trick was getting it to work on iPhone.
Setting preload=metadata works on desktop and android devices but not iPhone.
For iPhones I had to set it to autoplay so the poster image automatically appears on initial load. iPhones will prevent the video from auto playing, but the poster image appears as the result.
I had to do a check for iPhone using Pavan's answer found here. Detect iPhone Browser. Then use the proper video tag with or without autoplay depending on the device.
var agent = navigator.userAgent;
var isIphone = ((agent.indexOf('iPhone') != -1) || (agent.indexOf('iPod') != -1)) ;
$videoTag = "";
if(isIphone()) {
$videoTag = '<video controls autoplay preload="metadata">';
} else {
$videoTag = '<video controls preload="metadata">';
}
You can set preload='auto' on the video element to load the first frame of the video automatically.
Solution for #2, #3 etc. frames. We need attach disposable handler .one() for resetting default frame.
<video width="300" height="150" id='my-video'>
<source src="testvideo.mp4#t=2" type="video/mp4" />
</video>
$(function () {
let videoJs = videojs('my-video');
videoJs.one('play', function () {
this.currentTime(0);
});
});
I found a great way to dynamically add poster to a video!
To show the desired frame from video (in my case it's the frame at 1.75 seconds) - add preload="metadata" to the video element and #t=1.75 to the end of source URL.
Add eventListener to the video element that will listen for play event only once.
Once the event is emitted reset the video time.
<video width="100%" controls="controls" preload="metadata" id="myVid">
<source src="path/to/your/video#t=1.75" type="video/mp4">
</video>
<script>
var el = document.getElementById('myVid');
el.addEventListener('play', () => {
el.currentTime = 0;
}, { once: true });
</script>

Categories

Resources