Audio not working with VideoJS and video-hls - video.js

I am using VideoJS 5.10.2 and Video-contrib-hls 3.0.2 plugin to stream hls videos. Video is working fine. But audio is not working.
HTML code:
<video id="video_id" class="video-js vjs-default-skin" width="640" height="268">
<source src="url/hlsvideo.m3u8" type="application/x-mpegURL">
</video>
Javascript code:
videojs(document.getElementById('video_id'), {
"controls": true,
"autoplay": false,
"preload": "auto"
}, function() {
this.play();
});

Related

IntersectionObserver not registering on iOS, but works on Android, in Nuxt

What I have
I have made use of IntersectionObserver on my feed page. It behaves like TikTok. Scroll up or down to see the next video. On enter the video plays. On exit, it stops playing.
The Problem
It works on Android and Windows perfectly. On iOS, not so much. The videos are not autoplaying as expected. A bit strange though, is if I click the video (which calls play() on that video), and then scroll it out of view, the video does stop. When I scroll it back into view, it auto plays again. So I know that IntersectionObserver is being recognized, just not triggered initially.
The Code
==================================
The Feed Page, where the Observer is being instantiated:
data() {
return {
observer: null,
}
};
mounted() {
let config = { threshold: 0.1 };
if (process.client) {
if (/iPhone|iPad/i.test(navigator.userAgent)) {
config.root = null;
}
}
this.observer = new IntersectionObserver(function (entries) {
entries.forEach(({ target, isIntersecting }) => {
if (isIntersecting) {
target.play();
} else {
target.pause();
target.currentTime = 0;
}
});
}, config);
beforeDestroy() {
this.observer.disconnect();
},
HTML
<div
v-for="(post, index) in posts"
:key="index"
>
<MobileFeedItem :post="post" :observer="observer" />
</div>
=================================
The MobileFeedItem component
props: ["post", "observer"],
mounted() {
this.$nextTick(() => {
if (this.observer !== null && this.checkMediaTypeIsVideo(this.post)) {
this.observer.observe(
document.getElementById(
`video_${this.getContentId(this.post)}_mobile`
)
);
}
});
HTML
<video
:id="`video_${getContentId(post)}_mobile`"
:data-poster="getThumbnail(post)"
preload="none"
disablePictureInPicture
crossorigin
loop
playsinline
v-lazy-load
class="w-full h-full my-4"
>
<source :data-src="getMedia(post)" type="video/mp4" />
</video>
My Thoughts...
The observer is being instantiated and recognized, just not triggered. So is there a way that I can force the browser to wake up and become aware of the observer without having to click on each of the video elements first?
I found the answer. It wasn't anything wrong with the IntersectionObserver, but because my video was not muted.
"By default, autoplay executes only if the video doesn’t contain an audio track, or if the video element includes the muted attribute. Video playback pauses if the element gains an audio track, becomes unmuted without user interaction, or if the video is no longer onscreen"
source - https://developer.apple.com/documentation/webkit/delivering_video_content_for_safari
It also appears that we don't need intersection observer at all for Safari, as it does this for us. Huh.

Webpack hot reload doesn't stop html5 audio

In a Vue app I play background music, using the audio tag :
<audio id="music" autoplay loop>
<source
:src="musicfilename"
type="audio/mp3"
/>
</audio>
This works fine, but when the app is restarted during development, by Webpack 'hot reload', the music that was playing isn't stopped, so it keeps playing multiple music instances at the same time!
When I check with document.getElementsByTagName there is really only 1 instance of AUDIO, so I can't find a way to stop the previous audio instances from playing.
Any idea how to solve this problem?
You should track when your module is being hot replaced, and when it is just stop the audio player.
<audio id="music" ref="player" autoplay loop>
<source
:src="musicfilename"
type="audio/mp3"
/>
</audio>
export default {
...
mounted() {
if (module.hot) {
module.hot.dispose(this.hmrHandler);
}
},
destroyed() {
if (module.hot) {
module.hot.removeDisposeHandler(this.hmrHandler)
}
},
methods: {
hmrHandler() {
const { player } = this.$refs
player.pause()
// Lines below can also help
// player.currentTime = 0
// player.src = ''
},
},
...
}
Update:
Howler.unload() placed in the mounted hook solved the problem.
Webpack HMR API.
Look at dispose and removeDisposeHandler.

How to check if SOUND is ON/OFF on HTML5 video

I need to show Sound icon on top of the video, when sound is OFF and hide it when sound is ON. For some reason the code below is not working.
if (video.prop('muted') === true) {
video.mouseenter( function() {sound.show()} ).mouseleave( function() {sound.hide()} );
}
else {
sound.hide();
}
<video id="video" controls muted preload="none" width="446" height="250"></video>
I figured it out. Now it works like that.
video.mouseenter( function() {
if (video.prop('muted') === true) {
sound.show()
}
else {
sound.hide()
}
});
video.mouseleave( function() {
sound.hide();
});
Considering your video element:
<video id="video" controls muted preload="none" width="446" height="250">
</video>
You can determine whether sound is on by testing the volume and muted media properties of the element:
var video = document.getElementById("video");
if (video.muted || video.volume === 0) {
// Sound is off
}

ReferenceError: videojs is not defined

I am using video.js (in CDN-Mode) and everything seems to work fine (with Firefox 26.0). The video is embedded and works fine. But when I want to access the video-Object, I'm getting the console-error:
ReferenceError: videojs is not defined on the code-line where I want to access the object:
var myPlayer = videojs('example_video_1');
Googling arround could not solve my problem. I saw implementations where users used: V as constructor instead of videojs but this did not solve my problem).
This is my script, where I want to access the object:
<script type="text/javascript">
$("#button1").on("click", function(){
console.log( "You clicked a paragraph!" );
var myPlayer = videojs('example_video_1');
});
</script>
This is my header
<link href="http://vjs.zencdn.net/4.5/video-js.css" rel="stylesheet">
<script src="http://vjs.zencdn.net/4.5/video.js"></script>
<script language="javascript" type="text/javascript" src="js/jquery.js"></script>
And this is my video-declaration
<video id="example_video_1" class="video-js vjs-default-skin" controls
preload="auto" width="1270" height="720" poster="videos/search.png"
data-setup="{}">
<source src="videos/search.webm" type='video/webm'>
<p class="vjs-no-js">To view this video please enable JavaScript, and consider upgrading to a web browser that supports HTML5 video</p>
</video>
I would be happy for any kind of support.
A year and a half later and this issue occurred for me as well. I just installed it via npm install --save video.js and moved the file from the dist folder into my public scripts folder and it worked.
You must install or use from #videojs/http-streaming. I had same problem and solved by it.
I just made sure that the video.js file was the last attached script tag in the HTML. It worked for me.
import videojs from 'video.js';
try:
<script type="text/javascript">
$("#button1").on("click", function(){
console.log( "You clicked a paragraph!" );
var myPlayer = window.videojs('example_video_1');
});
</script>
add the event listener 'DOMContentLoaded' before calling the videojs object:
window.addEventListener('DOMContentLoaded', (event) => {
videojs('element-id', {
controls: true,
autoplay: false,
preload: 'auto'
});
});

Youtube iFrame javascript API onYouTubeIframeAPIReady not firing

This is from the Youtube API docs:
"As mentioned in the Getting started section, instead of writing an empty element on your page, which the player API's JavaScript code will then replace with an element, you could create the tag yourself."
But I cannot get the API to callback to my javascript. Any help would be great.
Here's my HTML code:
<iframe id="player" type="text/html" width="640" height="360"src="http://www.youtube.com/embed/1_QO8LoGNpc?enablejsapi=1" frameborder="0"></iframe>
JAVASCRIPT:
<script>
function onYouTubeIframeAPIReady() {
alert("hey");
player = new YT.Player('player', {
// height: '720',
// width: '1280',
// videoId: '1_QO8LoGNpc',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
</script>
I can get it to work with using javascript creating the iframe but not setting the iframe on the page. HELP!
Function onYouTubeIframeAPIReady() should be defined before loading https://www.youtube.com/iframe_api.
Here is the idea:
<iframe id="player" type="text/html" width="640" height="360"src="http://www.youtube.com/embed/1_QO8LoGNpc?enablejsapi=1" frameborder="0"></iframe>
<script>
function onYouTubeIframeAPIReady() {
alert("hey");
player = new YT.Player('player', {
// height: '720',
// width: '1280',
// videoId: '1_QO8LoGNpc',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
</script>
<script src="https://www.youtube.com/iframe_api"></script>
Why? Because iframe_api will call this function after being loaded. In your case iframe_api was loaded before.
Best regards.
But your code works. See it here:
http://jsfiddle.net/aXLA2/
<iframe id="player" type="text/html" width="640" height="360"src="http://www.youtube.com/embed/1_QO8LoGNpc?enablejsapi=1" frameborder="0"></iframe>
<script src="https://www.youtube.com/iframe_api"></script>