Is the AudioContext not working on mobile? (iPhone tested) - html5-audio

I read an article introducing HTML5 Web Audio API.
It's very interesting with my desktop Chrome.
However, is this not working for mobile?

The article seems to be about three years old. And back then the autoplay policy of browsers wasn't really affecting the usage of the Web Audio API. That has changed. Now it is required to have a user gesture (typically a click event) to start an AudioContext.
The first example of the referenced article would than look like this:
const $playButton = document.getElementById('play-button');
$playButton.addEventListener('click', () => {
const context = new AudioContext();
const oscillator = context.createOscillator();
oscillator.type = 'sine';
oscillator.connect(context.destination);
oscillator.start();
};
This does assume that you have a button with the id play-button somewhere in your HTML.
<button id="play-button">play</button>

Related

speechSynthesis.speak not working in chrome

I'm using chrome Version 55.0.2883.87 m (64-bit) on Windows 10.
The following simple html file reproduces the problem and is extracted from my more complex app. It is supposed to speak the 3 words on page load. It works on MS Edge and Firefox but does not work on chrome. This code was working for me on Chrome no problem a couple weeks back.
<html>
<head>
<script lang="javascript">
window.speechSynthesis.speak(new SpeechSynthesisUtterance("cat"));
window.speechSynthesis.speak(new SpeechSynthesisUtterance("dog"));
window.speechSynthesis.speak(new SpeechSynthesisUtterance("bark"));
</script>
</head>
<body></body>
</html>
I may never know for sure, because this problem was intermittent, but it seemed to go away after I started to cancel right before speak.
utter = new window.SpeechSynthesisUtterance("cat");
window.speechSynthesis.cancel();
window.speechSynthesis.speak(utter);
I don't think the cancel necessarily has to come between the utterance object creation and use. Just that it come before every speak. I may have had a different problem as I was only creating one utterance object, not a bunch. I did only see it on Chrome 78. Using Windows 7, 64-bit. Never saw the problem on Firefox or Edge.
EDIT 2 weeks later. No recurrences after several dozen tries. It seems .cancel() solved my problem. My symptoms were: calling speechSynthesis.speak() in Chrome would sometimes not start the speech. There were no immediate indications of a problem in the code, speechSynthesis.speaking would be true and .pending would be false. There would be no events from the utterance object. Normally, when speech would work, I'd get a 'start' event about 0.1 seconds after calling .speak().
speechSynthesis.speak() is no longer allowed without user activation in Google's Chrome web browser since 2018. It violates autoplay policy of Google Chrome. Thus Google Chrome has managed to revoke it's autoplay functionality but you can make use of it by adding a button to make a custom call.
You can visit here to check the status provided by chrome itself also below is the image attached which clearly shows that speechSynthesis.speak() call is prohibited without user's permission.
Link to image
Link to article by Google Chrome
To add to this, the issue for me was the playback rate on the instance of SpeechSynthesisUtterance was above 2. I discovered it must be set to 2 or less in chrome (although it works with higher rates in other browsers like safari).
In chrome, if the utterance rate is above 2, it causes the window.speechSynthesis to be stuck, and needs window.speechSynthesis.cancel() before it will play audio again (at a valid rate below 2) via .speak().
Did your text to voice tryout work only once? Here is why.
In chrome you have to cancel the speechSynthesis, otherwise its not compliant to googles autoplay policy. So you should start your script with:
window.speechSynthesis.cancel()
To cancel any speech synthesis that happened before.
resultsDisplay = document.getElementById("rd");
startButton = document.getElementById("startbtn");
stopButton = document.getElementById("stopbtn");
recognition = new (window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition || window.msSpeechRecognition)();
recognition.lang = "en-US";
recognition.interimResults = false;
recognition.maxAlternatives = 5;
recognition.onresult = function(event) {
resultsDisplay.innerHTML = "You Said:" + event.results[0][0].transcript;
};
function start() {
recognition.start();
startButton.style.display = "none";
stopButton.style.display = "block";
}
function stop() {
recognition.stop();
startButton.style.display = "block";
stopButton.style.display = "none";
}
.resultsDisplay {width: 100%; height: 90%;}
#stopbtn {display: none;}
<div class="resultsDisplay" id="rd"></div>
<br/>
<center>
<button onclick="start()" id="startbtn">Start</button>
<button onclick="stop()" id="stopbtn">Stop</button>
</center>
Try
utterance = new SpeechSynthesisUtterance("cat, dog, bark");
speechSynthesis.speak(utterance);
I made a Weave at LiveWeave.
Instead of specifying the text while calling new, you could try specifying an object with rate, volume, and text separately, and then converting it to voice.

Play video in the background in TVML

I'm starting a player and then pushing a document onto the navigation stack. Video is playing in the background but is not visible as the document is occupying the screen. Can anyone please tell me how to make the document transparent or is there any better approach to achieve the same?
Overlay TVML?
TVJS player property overlayDocument, see https://developer.apple.com/library/tvos/documentation/TVMLJS/Reference/TVJSPlayer_Ref/index.html or https://forums.developer.apple.com/thread/18431
You can get interactive overlay over videos as referred to in the following link:
http://devstreaming.apple.com/videos/wwdc/2016/212s41rh77qgdg26s86/212/212_developing_tvos_apps_using_tvmlkit_part_1.pdf
Overlays can be made interactive since you are essentially adding documents to overlay doc. So any kind of button lock up will work just fine.
Interactive overlay document is the way to go. The following code shows how this is done.
App.onLaunch = function(options) {
var singleVideo = new MediaItem('video', 'http://somevideo.mp4');
var videoList = new Playlist();
videoList.push(singleVideo)
var myPlayer = new Player();
myPlayer.playlist = videoList;
var parser = new DOMParser();
var parsedDoc = parser.parseFromString(`<document>
<alertTemplate>
<button>
<text>Click Me</text>
</button>
</alertTemplate>
</document>`, "application/xml");
myPlayer.interactiveOverlayDocument = parsedDoc;
myPlayer.interactiveOverlayDismissable = false;
myPlayer.play();
}
Apple doesn't have a lot of doc on it. but they did mention it in WWDC,
slide 98-102 of the WWDC 2016 presentation.
the end of this document-- Apple TV Markup Language Reference-- Compound Multimedia Elements
and an example in TVML Guide: Core concepts in TVML and TVMLKit-- Server/PlaybackVideo/index.js
This thing does have some bugs, namely the interactiveOverlayDismissable value not being active if the video is the first thing you display, or does this whole thing play well with the native code outside of TVML. But this is the easier part to do video background.
Note, you might want to add some even listeners to replay the video at the end, as the default behavior is to pop the view.

Record sound of a webaudio api's audio context

I am using web audio api in my project. Is there a way to record the audio data that's being sent to webkitAudioContext.destination?
.wav files are playing in my browser, so there should be some way to store that data into a (.wav) file . i know this is possible, but not yet find any solution :(
recorder.js can help me, but upto now i found it is only recording the microphone live input, is it possible to record my audio(.wav files) with the help of recorder.js? plz help
i am using this sample for recording https://github.com/mattdiamond/Recorderjs
I have managed to achieve this through a pure WebAudio solution (no Recorderjs needed). You can see it working fully on my discJS project and use the relevant source file to see how my complete code is working. I imagine this is only relevant to recording WebAudio nodes that you are playing yourself programmatically.
First you will need an HTML <audio> to use as a final destination. In this case I choose to show the controls so that the user may easily download the resulting file.
<audio id='recording' controls='true'></audio>
Now for the Javascript mojo:
const CONTEXT = new AudioContext();
var recorder=false;
var recordingstream=false;
function startrecording(){
recordingstream=CONTEXT.createMediaStreamDestination();
recorder=new MediaRecorder(recordingstream.stream);
recorder.start();
}
function stoprecording(){
recorder.addEventListener('dataavailable',function(e){
document.querySelector('#recording').src=URL.createObjectURL(e.data);
recorder=false;
recordingstream=false;
});
recorder.stop();
}
Now the final glue is that whenever you play an audio source, you also need to connect it to your recording stream:
function play(source){
let a=new Audio(source);
let mediasource=CONTEXT.createMediaElementSource(a);
mediasource.connect(CONTEXT.destination);//plays to default context (speakers)
mediasource.connect(recordingstream);//connects also to MediaRecorder
a.play();
}
This is a relatively primitive setup that works fine (tested on Firefox 52 and Chrome 70). For a more proper implementation, see MediaRecorder on MDN.
As found on the github: var rec = new Recorder(source [, config]), where source is an audio node. So it's up to you to put in the right node. If you play .wav files using <audio>, you can send it to the recorder:
<audio id="audio" src="" controls></audio>
var a = document.getElementById('audio');
var context = new webkitAudioContext();
var sourceNode = context.createMediaElementSource(a);
var rec = new Recorder(sourceNode);

Capture video without sound in Windows Store App

I want to write a Windows Store App that can capture video (without any sound) and take pictures. Imagine a digital camera: you can preview the picture on the screen of your device before pushing the button which takes the pic.
The problem I'm facing now is the fact that the Windows.Media.Capture namespace has only classes for objects that capture video with sound (CameraCaptureUI, MediaCapture). I'm not troubled by the objects' capabilities, but by the fact that I will have to include in the manifest of the app the Microphone capability and it does not make sense for the app to use it. I need a class that uses only the Webcam capability.
Any ideas?
I found the answer and I thought I should share it. I'm sorry for answering my own question, but here goes:
One can specify in the settings of the MediaCapture object, when initializing it, that it will use only the Video part:
var mediaCaptureMgr = new MediaCapture();
var captureSettings = new MediaCaptureInitializationSettings();
captureSettings.StreamingCaptureMode = StreamingCaptureMode.Video;
await mediaCaptureMgr.InitializeAsync(captureSettings);
RTFM!

HTML5 Videos in Mobile Safari Issue

Here is my scenario:
I am building a "kiosk" application in safari with 2 videos, one acting as a "screensaver" and the other is a supplementary video. The SS is looping fine via: (done on body onload="init()")
var myVideo = document.getElementById('screensaver');
myVideo.addEventListener('ended', playVideo, false);
function playVideo(){
var myVideo = document.getElementById('screensaver');
myVideo.play();
}
When the user taps the screen during the SS, it fades out $('#screensaver').fadeOut(1000); and the user is presented a question with a button to play the next video.
When the second video is done via:
$('#presentation').bind('ended', function(){
$(this).fadeOut(1000, function(){
$('#swapVideo').show(); //Overlay for user interaction
$('#screensaver').fadeIn(1000);
$('#screensaver').get(0).play();
});
});
The SS shows up, plays, but no longer loops. Are eventListeners lost when the display is set to none?
The same thing happens when I try to play the second video again. The 'ended' eventListener seems to be lost...
I believe that iOS ignores .play(). Apple believes it's best to prevent sites from automatically playing content, which could potentially eat up someone's data plan or create undesirable actions on iOS.
On iOS, .play() can only executed directly from a user interaction.
Documentation
As for your question, event listeners are not unbound if you change the display property.
Fiddle
$('.container').on('custom', function (evt) {
$(this).toggle();
});