How to check whether a video is audible? - javascript

A video has audio track and its volume is not zero or muted, but this video is not audible due to its audio track is in total quietness. I want to know how to check whether a video is audible, so I can toggle functions upon.
I found how to check whether a video has audio track from here. #upuoth's method works most browsers except IE10+. #brefd.it works for IE10+ but I didn't know how to use his code (please explain to me)
#upuoth's code
document.getElementById("video").addEventListener("loadeddata", function() {
if (typeof this.webkitAudioDecodedByteCount !== "undefined") {
// non-zero if video has audio track
if (this.webkitAudioDecodedByteCount > 0)
console.log("video has audio");
else
console.log("video doesn't have audio");
}
else if (typeof this.mozHasAudio !== "undefined") {
// true if video has audio track
if (this.mozHasAudio)
console.log("video has audio");
else
console.log("video doesn't have audio");
}
else
console.log("can't tell if video has audio");
});
#brefd's code
function hasAudio (video) {
return video.mozHasAudio ||
Boolean(video.webkitAudioDecodedByteCount) ||
Boolean(video.audioTracks && video.audioTracks.length);
}
var video = document.querySelector('video');
if(hasAudio(video)) {
console.log("video has audio");
} else{
console.log("video doesn't have audio");
}
I prepared three video clips, one with an audio track, one without audio track and one with an audio track but isn't audible. The code I found above only works for the fisrt two clips but for the third one. Please let the alert be "not audible" when playing the third clip by using the code from JSfiddle link.

Below is the merged code of above that you can replace with in your JSFiddle:
document.getElementById("myVideo").addEventListener("loadeddata", function() {
if (typeof this.webkitAudioDecodedByteCount !== "undefined") {
if (this.webkitAudioDecodedByteCount > 0)
alert("This video has a track");
else
alert("no track");
} else if (typeof this.mozHasAudio !== "undefined") {
if (this.mozHasAudio)
alert("This video has a track");
else
alert("no track");
} else if (typeof this.audioTracks !== "undefined") {
if (this.audioTracks && this.audioTracks.length)
alert("audible");
else
alert("not audible");
} else
alert("Not sure");
});
Unfortunately, I doubt if there would be a way to detect "not audible" audio tracks.

There are different ways to check whether a video file has audio or not, one of which is to use mozHasAudio, video.webkitAudioDecodedByteCount and video.audioTracks?.length properties of video, clean and simple...
const video = component.node.querySelector("video");
video.onloadeddata = function() {
if ((typeof video.mozHasAudio !== "undefined" && video.mozHasAudio) ||
(typeof video.webkitAudioDecodedByteCount !== "undefined" && video.webkitAudioDecodedByteCount > 0) ||
Boolean(video.audioTracks?.length)) {
console.log("This video has audio tracks.");
} else {
console.log("This video has no audio tracks.");
}
};

Related

Why would FireFox Mobile have issues with navigator.mediaDevices.getUserMedia?

if (Chat.Settings.videodevice != "NONE") addMediaOption(window.videoSelect, "NONE", "NONE");
if (Chat.Settings.audiodevice != "NONE") addMediaOption(window.audioSelect, "NONE", "NONE");
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((stream) => {
navigator.mediaDevices.enumerateDevices().then((devices) => {
let audiocount = 0;
let videocount = 0;
devices.forEach(device => {
let element = null;
let label = "";
if ('audioinput' === device.kind) {
audiocount++;
element = window.audioSelect;
label = device.label || `Microphone #${audiocount}`;
}
if ('videoinput' === device.kind) {
videocount++;
element = window.videoSelect;
label = device.label || `Video #${videocount}`;
}
if (!element || device.deviceId == "") return;
addMediaOption(element, device.deviceId, label);
});
stream.getTracks().forEach((track) => track.stop());
if (Chat.Settings.videodevice != "NONE") PreviewBroadcast(Chat.Settings.videodevice);
});
//document.getElementById('modal-exit').classList.add("visible");
document.getElementById('modal-back').classList.add("visible");
Modal.Center();
}).catch(err => {
Message.receive.public(`${err}`);
console.log(err); /* handle the error */
if (err.name == "NotFoundError" || err.name == "DevicesNotFoundError") {
//required track is missing
} else if (err.name == "NotReadableError" || err.name == "TrackStartError") {
//webcam or mic are already in use
} else if (err.name == "OverconstrainedError" || err.name == "ConstraintNotSatisfiedError") {
//constraints can not be satisfied by avb. devices
} else if (err.name == "NotAllowedError" || err.name == "PermissionDeniedError") {
//permission denied in browser
} else if (err.name == "TypeError" || err.name == "TypeError") {
//empty constraints object
} else {
//other errors
}
});
I perform permission check with initial getUserMedia, this allows me to obtain device labels to properly identify DeviceId by name/etc.
I enumerate to populate audio/video selection so it can be saved for future use.
When a video item is selected, I run previewBroadcast which runs Navigator.mediaDevices.getUserMedia(SavedConstraints) but problem is it doesn't catch any errors or reveal a useable stream. This issue doesn't occur on desktop browsers at all but testing mobile FireFox failed amongst the few supported browsers.
I'm experimenting and trialing stuff by removing/adding code type stuff but curious what's causing this issue. I can say DeviceId matches 100% each time,
The problem makes getting the stream very iffy, as in it may or just doesn't work. Any tips I'd appreciate.

Video paused on inactive tab

I have implemented hacktimer HackTimer project and i got nice game working even in inactive tab (background). I have part with video and video also works fine - after activate tab in chrome they speed up for secound to get perfect currentDuration. Now same code not working any more. Video go to pause regime in the moment of inactivity. When i go back to tab video start to play.
I have no idea what can be.
My OS: windows Chrome version: Version 80.0.3987.149 (Official
Build) (64-bit)
My html tag looks like:
<video id="videoID" muted playsinline
oncanplaythrough="console.log('video ready');">
<source src="1.ogv" type="video/ogg">
<source src="1.mp4" type="video/mp4">
no support
</video>
I just wanna permament playing like youtube did.
Only solution for last version was : Visibility api .
hackTimer works fine all the time but inactivating tab makes pause() call.
I just put on visibilityChange event code line video.play() .
Code:
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") {
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
var videoElement = document.getElementById("videoElement");
function handleVisibilityChange() {
if (document[hidden] && videoElement.style.display != 'none') {
videoElement.play();
}
}
if (typeof document.addEventListener === "undefined" || hidden === undefined) {
console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
// Handle page visibility change
document.addEventListener(visibilityChange, handleVisibilityChange, false);
}
For my app if video is visible then play but other people can add also this line :
if (video.paused) {
video.play()
}

saving both checkbox and audio state to local storage

I am trying to save to local storage the state of both a checkbox (checked/unchecked) and audio (play/pause). The default state of the checkbox is checked and audio is playing (looping) as seen in the code below.
So if the checkbox is checked, audio is playing and both should be saved to local storage (checkbox checked and audio playing).
Else if the checkbox is unchecked, audio is paused and both should be saved to local storage (checkbox unchecked and audio paused).
The problem I have is with saving the state of the checkbox and audio after it's been checked again.
Steps in reproducing the issue:
1) uncheck checkbox > audio stops > refresh browser > works
2) check checkbox > audio playing > refresh browser > not working, checkbox unchecked and audio not playing
Here is the javascript:
if (window.localStorage.getItem("musicState") != null) {
var music = window.localStorage.getItem("musicState");
if (music == "true") {
status = 'pause';
$("audio").trigger(status);
}
else {
status = 'pause';
$("audio").trigger(status);
$("input:checkbox[name='music']").removeAttr("checked");
}
}
$("input:checkbox[name='music']").click(function () {
var visMusic = "play";
if (status == 'pause') {
status = 'play';
} else {
status = 'pause';
}
$("audio").trigger(status);
window.localStorage.setItem("musicState", visMusic)
});
here is the HTML:
<audio autoplay loop>
<source src="audio/music.mp3" type="audio/mpeg">
</audio>
<label><input type="checkbox" name="music" checked></label>
In your checkbox's click callback you are setting visMusic as "play". You never update it before storing it in localStorage as "musicState". This means that no matter what you do, "musicState" is always going to equal "play".
In your if-statement at the top (where you are retrieving from localStorage) you are testing if what you stored is "true". It is not, and never will be, because it is always "play". Your code is always going to your else which pauses the music and unchecks the box.
Here is an updated version that should work:
if (window.localStorage.getItem("musicState") != null) {
var music = window.localStorage.getItem("musicState");
if (music == "true") {
status = 'play';
$("audio").trigger(status);
}
else {
status = 'pause';
$("audio").trigger(status);
$("input:checkbox[name='music']").removeAttr("checked");
}
}
$("input:checkbox[name='music']").click(function () {
var visMusic = "false";
if (status == 'pause') {
status = 'play';
visMusic = "true";
} else {
status = 'pause';
}
$("audio").trigger(status);
window.localStorage.setItem("musicState", visMusic)
});

addEventListener click being fired multiple times within a flickity slider

I'm using flickity, which is a bit irrelevant, and on first load and for each 'change' of a slide I'll search the slide for any videos that have audio enabled (set as a data attribute via PHP via CMS) and then it'll autoplay the video and if the user clicks an unmute button then it'll unmute and vice versa.
This worked fine going forward but going back once the mute button is clicked, the eventListener for the click will fire every time it's existed. I'm guessing the eventListener is being added to each time but I can't work out how to remove the eventListener.
Any help on how to prevent the muteButton.addEventListener('click') from being fired more than once?
//
playVideo = function(index) {
var videos, video, muteButton = null, hasAudio = false;
// Pause all other slide video content if it was playing
flkty.cells.forEach(function(cell, i) {
videos = cell.element.querySelectorAll('video.--autoplay');
videos.forEach(function(video) {
if (video !== null && typeof video !== 'undefined') {
if (!video.paused) {
video.pause();
}
}
});
});
// For current slide
if (index == flkty.selectedIndex) {
videos = flkty.selectedElement.querySelectorAll('video.--autoplay');
muteButton = flkty.selectedElement.querySelector('a.button__mute');
// If videos exist on the current slide
if (videos.length) {
videos.forEach(function(video, index) {
if (video !== null && typeof video !== 'undefined') {
video.play();
if (muteButton !== null && typeof muteButton !== 'undefined' && index == 0) { // Only fire this once per video (as mute = mute all)
console.log(muteButton);
muteButton.addEventListener('click', function(e) {
e.preventDefault();
console.log('clicked'); // TOFIX; fires multiple times
muteVideo(videos, video, muteButton, true);
});
}
}
return;
});
}
}
};
flkty.on('select', function(event, index) {
if (index === 0) {
playVideo(index);
return false;
}
});
flkty.on('change', function(index) {
playVideo(index);
});
//
muteVideo = function(videos, video, muteButton, hasAudio) {
console.log('hasAudio');
if (videos.length > 1) {
videos.forEach(function(video, index) {
if (video.muted == true) {
video.muted = false;
if (index == 0) {
$(muteButton).text('mute');
}
} else {
video.muted = true;
if (index == 0) {
$(muteButton).text('unmute');
}
}
});
} else {
if (video.muted == true) {
$(muteButton).text('mute');
video.muted = false;
} else {
$(muteButton).text('unmute');
video.muted = true;
}
}
};
Just use removeEventListener().
To remove event handlers, the function specified with the addEventListener() method must be an external function.
Anonymous functions, like yours, will not work.
As for only attaching it once: Just set a flag to be checked before adding the eventhandler in the first place.
Don't use removeEventListener() in this case. The real problem is that you are adding event listeners each time your playVideo() function is called. So the problem you should solve is to make sure you only add the event listeners once, probably when the page initializes or something.
Here is what I would do:
Extract the "add event listener code" into a separate function, addButtonListeners() by removing that piece of code from the playVideo(). Then call the addButtonListeners() once when your page is loaded.

Pause HTML5 video to lighten resource load?

I have a website that has one of those annoying autoplay looping background videos that just play over and over forever instead of using just a picture. I was wondering if it would lighten the resource load on our users machines if I paused the video when they are not looking at my page through the new page visibility API?
To all the geniuses on this site, I would love to see an answer that shows how you determined your answer. I am sort of new to the front-end world and I'm not sure how I would figure this question out.
#stupidkid
Though it has been asked long before, the best solution for you is here : https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
function handleVisibilityChange() {
if (document[hidden]) {
//pause video
} else {
//play video
}
}
document.addEventListener(visibilityChange, handleVisibilityChange, false);
Please try this.

Categories

Resources