Angular 2, video duration access. - html

Im trying to get video duration from my videos that i listed in a table. I tried to access it using #ViewChildren and was successful until one part. i get the query list but when i try accessing _results it returns undefined. Later I learned that queryList was private for some reason. Any help will be appreciated
Here is my code:
<video id="video1" #video>
<source src = "{{videos.link}}" type="video/mp4">
</video>
#ViewChildren('video') video;
ngOnInit: {
Observable.timer(1000,1000).subscribe(() => {
if(this.video && !this.isVideoLogged){
console.log(this.video);
this.isVideoLogged = true;
}
}

You can use the loadedmetadata event:
Plunker example
<video width="480" controls #video (loadedmetadata)="onMetadata($event, video)"
onMetadata(e, video) {
console.log('metadata: ', e);
console.log('duration: ', this.duration = video.duration);
}

Related

Angular 9 one-way binding not working on HTML5 video

I have the following HTML5 snippet in home-component.html:
<div id="main-tv-cabinet">
<video id="tv" autoplay preload="auto" controls
width="640" height="480"
(ended)="onTvPreviewEnded()">
<source src="{{sermonForPreview}}" type="video/mp4">
Sorry, your browser doesn't support embedded videos.
</video>
</div>
My view model is as follows:
export class HomeComponent {
private sermonIndexForPreview : number = 0;
private sermonsForPreview : string[] = [];
public sermonForPreview = "";
constructor()
this.sermonsForPreview.push("assets/videos/previous-sermon-snippet-1.mp4");
this.sermonsForPreview.push("assets/videos/previous-sermon-snippet-2.mp4");
this.sermonForPreview= this.sermonsForPreview[0];
}
}
public onTvPreviewEnded(){
this.sermonIndexForPreview = (this.sermonIndexForPreview + 1) % 2;
this.sermonForPreview = this.sermonsForPreview[this.sermonIndexForPreview];
this.restartVideoPlayer();
console.log(this.sermonForPreview);
}
private restartVideoPlayer() {
var tvScreen: any = document.getElementById("tv");
// TO FIGURE: why is binding not working here?
tvScreen.src = this.sermonForPreview;
if (tvScreen.paused)
tvScreen.play();
else tvScreen.pause();
}
}
When the video ends playing the first one, I expect the second to play and when the second one is done, back to the first, etc. The loopback is happening but the video element is stuck with whatever video is first in the list unless I comment out the line
tvScreen.src = this.sermonForPreview;
I understand that one-way binding should reflect changes in the view model back to the view. I even tried two-way biding with the [()] syntax but that did not solve it. What did I miss?
Take a look at StackBlitz I've created.
https://stackblitz.com/edit/angular-ivy-ela9eq
Your binding was not working as you tried to set src attribute to the video tag, not the source tag.
You were combining Angular's data binding and basic JavaScript (in your restartVideoPlayer() method). You should think in declarative way and use just the binding if you can.

HTML video tag does not display video correctly

I am trying to use Cordova Media Capture to play video however, it does not work.
Here is my JS:
function video() {
navigator.device.capture.captureVideo(onSuccess, onFail,
{
limit: 1,
duration: constants.MAX_DURATION_OF_VIDEO
});
function onSuccess(mediaFiles) {
console.log("MEDIA FILE");
console.log(mediaFiles);
var i, path, len;
for (i = 0, len = mediaFiles.length; i < len; i += 1) {
path = mediaFiles[i].localURL;
console.log(path);
$state.go('submitMoment', {picture: $sce.trustAsResourceUrl(path)});
}
};
function onFail(message) {
console.log("FAILED because: " + message);
}
};
I have tried both FullPath and localURL. I'm using localURL here because this video is being taken from the user's phone and I get an error from the browser. It is sandboxed so I cannot use a localURL coming from an external device. The device returns a video in mp4 format.
Here is how it looks when I display it on the next screen in '$state.go'
The controls appear fine but when you play the video nothing happens. It's just a white screen.
Once the video is done playing it just disappears:
Here is my HTML:
<video width="100%" height="300px" controls>
<source src="{{vm.picture}}" type="video/mp4"></source>
</video>
This is some strange behavior. Does anyone know whats going on?
Thanks.
EDIT:
Console display:
This is the error I get when I use 'fullPath' because of this I decided to use the localURL instead and I don't get the error. Also, it seems like the white screen bug isn't really a bug. If i tap it the controls show up but it is still stuck on play (The first screenshot).
In the onSucess method, store media url as
$scope.videoSrc = mediaFiles[0].fullPath;
$state.go('submitMoment', {picture: $scope.videoSrc);
Receive picture as $stateParams in your new Page.
$scope.videoUrl = $stateParams.picture;
In your HTML
<source src="{{videoUrl}}" type='video/mp4' />
In your controller inject the $stateParams dependency.
Hope this helps you.

HTML5 video: click on play button, play another video

I need to change the video link on click on Play button and also need to auto play the video.
<video id="video" src="dhoni.mp4" width="320" height="240" controls>
</video>
<script>
$(document).ready(function () {
var video = document.getElementById('video');
video.onplay = function (e) {
$('video').attr({'src': 'ran.mp4'});
$('video')[0].play();
};
});
</script>
Exists many kinds of solution for what you want, I made an example how you do it
The simple way is just make two videos the first become hidden when the second is playing.
The other way is like the first but you use a image to represent the video1 when the user click in the image, so the video2 start, and you hide the image when the user click.
The others solutions like you're trying is more complicated because if you try to replace the src atribute of a video by other src exist a problem to load this, this involve ajax blob request and this will cause much issues to handle, for example when I trying to load a video that's not hosted in my server, and other things like the how the way firefox, chrome and other browsers render the video.
https://jsfiddle.net/5mek5ffd/27/
HTML
<video id="video1" src="http://techslides.com/demos/sample-videos/small.mp4" width="320" height="240" controls>
</video>
<video id="video2" class="hidden" src="https://static.videezy.com/system/resources/previews/000/004/147/original/jelly-fish.mp4" width="320" height="240" controls="">
</video>
CSS
.hidden{ display:none }
JS
function changeVideo(video1, video2){
try {
// pause the video
jQuery(video1)[0].pause();
// set the seconds to 0
jQuery(video1)[0].currentTime = 0;
// add the hidden class to the video1
jQuery(video1).addClass("hidden");
// remove the hidden class to the video2
jQuery(video2).removeClass("hidden");
// pause the video2 - it's necessary cause the video was ended
jQuery(video2)[0].pause();
// set the seconds to 0 to the video 2
jQuery(video2)[0].currentTime = 0;
} catch(e){
// if something goes wrong put the message on console
//prevent the script stop the other scripts too
console.log(e.message);
return false;
}
}
jQuery(document).ready(function($){
try {
// if exists the video1 put it on video1 variable
// if exists the video2 put it on video2 variable
var $video1 = $('#video1').length > 0 ? jQuery('#video1') : false,
$video2 = $('#video2').length > 0 ? jQuery('#video2') : false;
// if exists the video1 and video 2
if($video1 && $video2){
// if the #video1 is starting to play
$video1.on("play", function() {
console.log($video2[0].duration);
// call change video function
changeVideo("#video1","#video2");
// the [0] represents the javascript dom object
// if the seconds is 0 in my video 2 then play it
if($video2[0].currentTime == 0 )
$video2[0].play();
});
// start the video1 if the page is ready added 1 sec for delay,
// to not cause the impress wrong of the video
setTimeout(function() {
if($video2[0].currentTime == 0)
$video1[0].play();
},1000);
// if the video was ended return to the first video
$video2.on("ended", function(){
changeVideo("#video2","#video1");
});
}
} catch(e){
// if something goes wrong put the message on console
//prevent the script stop the other scripts too
console.log(e.message);
}});

One bind "ended" for all videos [html5]

i need to increment a variable each time a video has been watched (no matter which one), so i can display an ad when this variable reach 10.
Actually i bind every video using their ID.
<video id="1">...</video>
<video id="2">...</video>
<video id="3">...</video>
$('#'+idVideo).bind('ended',function(){ /* each time i append a video, i do this */
WATCHED_VIDEOS++;
// displayAd() when WATCHED_VIDEOS reach 10....
});
I tried this line $('video').bind('ended',function(){...}); instead of binding every video but it doesn't work.
Anyone has a solution to accomplish this using only one bind? Thanks
try the following:
<video id="1">...</video>
<video id="2">...</video>
<video id="3">...</video>
<script>
var total_ended = 0;
var videos = document.getElementsByTagName('video');
for (i=0;i<videos.length;i++) {
videos[i].onended = function() {
total_ended++;
console.log('Total videos ended: ' + total_ended);
}
}
</script>
and here's a working example: http://jsfiddle.net/xvLmam41/
hope that helps.

Start function if HTML <audio> tag starts the song

I want to start a function if someone turn the music on.
<audio controls autobuffer>
<source src="./songs/test.mp3" />
</audio>
So I use the standard controls and if someone clicks the play button I want to start a function.
Can someone help me?
I don't find a solution...
Yours Alex.
Thanks for your help.
I got the solution here:
function playSound() {
// source is global so we can call .noteOff() later.
var audio = document.querySelector('audio');
audio.addEventListener(
'play',
function(e) {
alert($('audio source').attr('src'));
// Do Something.
},
false
);
}
Use play event:
var audio = document.querySelector('audio');
audio.addEventListener(
'play',
function(e) {
// Do Something.
},
false
);