Steam Browser with html5 audio tag - javascript

I'm currently making a small app, which main use will be from the steam browser. However im having some issues getting audio tags to play. Though the site http://html5test.com/ suggests that it does support the audio tags.
Has anyone else had success with such things in the steam browser?
I've tried with several file formats, .wav, .mp3, .ogg
Heres the code, it works fine in IE10, FF and Chrome.
JS
<script type="text/javascript">
var lastPlayer = null;
var loopAudio = false;
function play_sound(file)
{
if (is_playing()) { return }
lastPlayer = file;
lastPlayer.addEventListener('ended', function() {
if (loopAudio == true) {
lastPlayer.play();
}
}, false);
lastPlayer.play();
};
function stop_sound()
{
lastPlayer.pause();
lastPlayer.currentTime = 0;
};
function loop_sound()
{
if (loopAudio === false) { loopAudio = true }
else { loopAudio = false }
};
function is_playing()
{
if (lastPlayer === null) { return false; }
else { return !lastPlayer.ended && 0 < lastPlayer.currentTime; }
};
</script>
HTML
<audio id="Calm_waves" src="http://localhost/Calm_waves.mp3" preload="none"></audio>
<button class="span2 btn btn-large btn-primary" onclick="javascript:play_sound(Calm_waves);">Calm Waves</button>

Further tinkering i managed to get this working using the ogg format, though i tried this format before, i tried again using one of the recommended converters from the WebM projects site. http://www.mirovideoconverter.com/

Related

How to play sound in javascript?

I create websocket server in python to handle notification event. Now, i can receive notification, the problem is i can't play sound because new autoplay policy changed, if i play sound using javascript it give me domexception. Any suggestion please ?
As i know, playing sound is simple in html-javascript. like this example: https://stackoverflow.com/a/18628124/7514010
but it depend to your browsers and how you load and play, so issues is:
Some of browsers wait till user click something, then let you play it (Find a way for it)
In some case browsers never let you play till the address use SSL (means the HTTPS behind your url)
The loading be late so the playing be late / or even not start.
So i usually do this:
HTML
<audio id="notifysound" src="notify.mp3" autobuffer preload="auto" style="visibility:hidden;width:0px;height:0px;z-index:-1;"></audio>
JAVASCRIPT (Generally)
var theSound = document.getElementById("notifysound");
theSound.play();
And the most safe if i want sure it be played when i notify is :
JAVASCRIPT (In your case)
function notifyme(theTitle,theBody) {
theTitle=theTitle || 'Title';
theBody=theBody || "Hi. \nIt is notification!";
var theSound = document.getElementById("notifysound");
if ("Notification" in window && Notification) {
if (window.Notification.permission !== "granted") {
window.Notification.requestPermission().then((result) => {
if (result != 'denied') {
return notifyme(theTitle,theBody);
} else {
theSound.play();
}
});
} else {
theSound.play();
try {
var notification = new Notification(theTitle, {
icon: 'icon.png',
body: theBody
});
notification.onclick = function () {
window.focus();
};
}
catch(err) {
return;
}
}
} else {
theSound.play();
}
}
(and just hope it be played. because even possible to volume or some customization make it failed.)
to bypass new autoplay policy :
create a button that can play the sound, hide it and trigger the sound with :
var event = new Event('click');
playBtn.dispatchEvent(event);
EDIT
assuming you have :
let audioData = 'data:audio/wav;base64,..ᴅᴀᴛᴀ...'; // or the src path
you can use this function to trigger whenever you want without appending or create element to the DOM:
function playSound() {
let audioEl = document.createElement('audio');
audioEl.src = audioData;
let audioBtn = document.createElement('button');
audioBtn.addEventListener('click', () => audioEl.play(), false);
let event = new Event('click');
audioBtn.dispatchEvent(event);
}
usage :
just playSound()
EDIT 2
I re test my code and it does'nt work hum ... weird

safari ios audio- refusing to play with error

The javascript error is: Unhandled Promise Rejection: NotAllowedError: The request is not allowed by the user agent or the platform in the current context, possibly because the user denied permission.
My setup works across other browsers, desktop and mobile.
The way it works is:
have a flag first_audio_played = false;
add a touch event listener that plays some audio, and sets first_audio_played = true; (then removes the touch listener)
all subsequent audio checks if(first_audio_played) some_other_audio.play();
this way, only the first audio played requires direct user input. after that, all audio is free to be triggered by in-game events, timing, etc...
this appears to be the "rule" for audio across most browsers. is the iOS "rule" that every audio needs to be triggered by user input? or is there some other step I'm missing?
For my javascript game, sounds stopped working on iOS recently. They all have readyState=4, but only the sound I played on tap works, the others won't play. Maybe you could play all the sounds on the first tap. But the solution I found that works for now for me is to load all the sounds from ajax arraybuffers and use decodeAudioData(). Then once you've played 1 sound from user tap (on not the body), they all play whenever.
Here is my working code where the second way of doing it is on bottom. When I tap to play sound2, sound1 starts working also.
<html>
<body>
<div id=all style='font-size:160%;background:#DDD' onclick="log('clicked');playSound(myAudio)">
Sound1 should be playing every couple seconds.
<br />Tap here to play sound1.
</div>
<div id=debug style='font-size:120%;' onclick="playSound(myAudio2)">
Tap here to play the sound2.
</div>
<script>
var url = "http://curtastic.com/drum.wav"
var url2 = "http://curtastic.com/gold.wav"
var myAudio, myAudio2
if(0)
{
var playSound = function(sound)
{
log("playSound() readyState="+sound.readyState)
log("gold readyState="+myAudio2.readyState)
sound.play()
}
var loadSound = function(url, callback)
{
var audio = new Audio(url)
audio.addEventListener('canplaythrough', function()
{
log('canplaythrough');
if(callback)
callback()
}, false)
audio.load()
if(audio.readyState > 3)
{
log('audio.readyState > 3');
if(callback)
callback()
}
return audio
}
myAudio = loadSound(url, startInterval)
myAudio2 = loadSound(url2)
}
else
{
var playSound = function(sound)
{
log("playSound()")
var source = audioContext.createBufferSource()
if(source)
{
source.buffer = sound
if(!source.start)
source.start = source.noteOn
if(source.start)
{
var gain = audioContext.createGain()
source.connect(gain)
gain.connect(audioContext.destination)
source.start()
}
}
}
var loadSound = function(url, callback)
{
log("start loading sound "+url)
var ajax = new XMLHttpRequest()
ajax.open("GET", url, true)
ajax.responseType = "arraybuffer"
ajax.onload = function()
{
audioContext.decodeAudioData(
ajax.response,
function(buffer)
{
log("loaded sound "+url)
log(buffer)
callback(buffer)
},
function(error)
{
log(error)
}
)
}
ajax.send()
}
var AudioContext = window.AudioContext || window.webkitAudioContext
var audioContext = new AudioContext()
loadSound(url, function(r) {myAudio = r; startInterval()})
loadSound(url2, function(r) {myAudio2 = r})
}
function startInterval()
{
log("startInterval()")
setInterval(function()
{
playSound(myAudio)
}, 2000)
}
function log(m)
{
console.log(m)
debug.innerHTML += m+"<br />"
}
</script>
</body>
</html>
You can use either [WKWebViewConfiguration setMediaTypesRequiringUserActionForPlayback:WKAudiovisualMediaTypeNone] or [UIWebView setMediaPlaybackRequiresUserAction:NO] depending on your WebView class (or Swift equivalent).

Youtube video not loading with playlists

I'm having problems enqueuing a playlist using the YouTube IFrame API.
(https://developers.google.com/youtube/iframe_api_reference#Queueing_Functions)
I'm using flash to show the youtube videos. Using HTML5 shows another issue where the videoplayback call is called multiple times before the video loads.
On loading the playlist, the video itself doesn't load. It shows up in the network tab
as a call to videoplayback that is 'pending' until it times out after 7.5 minutes at which point it tries again and everything works. The playlist, incidentally, has loaded successfully - mousing over the youtube iframe shows a loaded playlist.
The code to replicate this is below, and the issue is found following these steps:
1. Click a channel
2. If channel loads, goto 1, else check network tab.
I know the method of replication is contrived, however I'm seeing this 'sometimes'
on first load.
The playing channel isn't at fault - this has been seen with many different channels.
Is it my code? Is there a work around? Is there a fix?
Tested on Windows 7 32bit using Chrome 28, Firefox 22.0 and IE 10
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<meta content="text/html;charset=utf-8" http-equiv="Content-Type">
<title>
Youtube Test
</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
<script type='text/javascript'>
var collection = [];
var player = null;
var playlistEnqueued = false;
function clear() {
// Removes the iframe.
if (player !== null) {
player.destroy();
}
collection = [];
playlistEnqueued = false;
player = null;
}
function createYT(videoId) {
// Clear anything that's up currently
clear();
// Yes, this could be $.ajax, however this way reduces the dependency on jQuery
// further for the purposes of this test.
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
parseJSONResponse(JSON.parse(xmlhttp.responseText));
}
}
xmlhttp.open("GET", "https://gdata.youtube.com/feeds/users/" + videoId + "/uploads?alt=json", true);
xmlhttp.send();
}
function parseJSONResponse(data) {
var feed = data.feed;
$.each(feed.entry, function(index, entry, list) {
collection.push(entry.id.$t.match('[^/]*$')[0]);
});
playVideo();
}
function playVideo(videoId) {
try {
if (videoId === undefined || videoId === null) {
videoId = collection[0];
}
if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
window.onYouTubeIframeAPIReady = function() {
playVideo(videoId);
};
$.getScript('//www.youtube.com/iframe_api');
} else {
if (playlistEnqueued === true) {
player.playVideoAt(0);
} else {
player = new YT.Player('video', {
events: {
'onReady':function(event) {
try {
player.cuePlaylist(collection);
} catch (e) {
console.error(e);
}
},
'onError':function(error) {
console.error(error);
}
},
videoId: videoId,
width: 425,
height: 356,
playerVars: {
autoplay: 1,
}
});
// Attaching event listener after object creation due to
// http://stackoverflow.com/questions/17078094/youtube-iframe-player-api-onstatechange-not-firing
player.addEventListener('onStateChange', function(state) {
try {
stateChanged(state);
} catch (e) {
console.error(e);
}
});
}
}
} catch (e) {
console.error(e);
}
}
function stateChanged(state) {
// This state will be called on enqueueing a playlist
if (state.data == 5) {
playlistEnqueued = true;
playVideo();
}
}
$(document).on('ready', function() {
var player = $(document).find("#player");
$("a").on('click', function() {
var channel = $(this).attr('data-channel');
createYT(channel);
return false;
});
});
</script>
</head>
<body>
<div class='test'>
<div id='video'>
</div>
<a href='#' data-channel='mit'>MIT</a>
<a href='#' data-channel='tedtalksdirector'>TED</a>
<a href='#' data-channel='minutephysics'>Minute Physics</a>
</div>
</body>
</html>
When using flash, and on waiting for the video connection to timeout and try again the following is seen in the network tab. As you can see it's 'pending', failed, and then tried again after 7.5 minutes.
Chrome network tab once the video starts playing:
Chrome network tab on video playback
More images when I get past 10 reputation...
I've got this up and running on jsFiddle (http://jsfiddle.net/3Bm2V/5/) and it seems to be working ok. I did have to change the
$(document).on('ready', function () {
to
$(function() {
to get it to work in jsFiddle, so try the link above and see if it works for you now?

HTML5 Audio does not play more than once

this does not work for me! anyone having the same issue? my code seems straightforward but it only plays once I need to be able to play over and over. see as follows:
My Html:
<audio id="siren" src="sounds/400.ogg" preload="auto">
and my JS:
function play_siren() {
log("play sound");
if(document.getElementById('siren').paused == true){
document.getElementById('siren').play();
}
}
function pause_siren() {
try{
if(document.getElementById('siren').paused == false){
document.getElementById('siren').pause();
}
log("paused siren");
}catch(err){
log(err.message);
}
try{
if(document.getElementById('siren').currentTime > 0.0){
document.getElementById('siren').currentTime = 0.0;
}
log("reset siren");
}catch(err){
log(err.message);
}
}
it is started programmatically in the JS code as follows:
if(Obj[3].siren == true && isPlayingSiren == false){
play_siren();
isPlayingSiren = true;
}else if(Obj[3].siren == false && isPlayingSiren == true){
pause_siren();
isPlayingSiren = false;
}
I found this gentleman's code and his DOES seem to work: http://html5.komplett.cc/code/chap_video/js_audioPlayer_en.html
But setting "currentTime = 0" is not doing anything for me.
I can't figure it out. I tested with Chrome, Firefox and Safari. Firefox does not work at all so far Chrome seems to be the best for HTML5 but still I can only play once.
I even tried mp3 and ogg same behavior.
Please shed some light. Thank you!
here is full HTML:
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" media="all" href="js_audioPlayer.css">
<title>HTMLMediaElement example - Audio Player</title>
<script src="../js/audioPlayer.js"></script>
</head>
<body>
<fieldset>
<audio src="sounds/400.ogg" preload="auto"></audio>
<legend>Audio Player (400)</legend>
</fieldset>
<script>
function loadXMLDoc(){
_pause();
updateProgress(0);
playPause();
}
var loadXmlTimer = setInterval(loadXMLDoc, 2000);
</script>
</body>
</html>
and here is full javascript:
// global callback functions
var playPause, updateProgress, _play, _pause;
/* initialize audio player */
window.onload = function() {
// keep track of playback status
var AudioStatus = {
isPlaying : false
};
// define references to audio, pulldown menu, play-button, slider and time display
var audio = document.querySelector("AUDIO");
/* load track by menu-index */
var loadTrack = function(idx) {
audio.src = '../sounds/400.ogg';
audio.load();
};
/* callback to play or pause */
_play = function() {
audio.play();
log("play");
AudioStatus.isPlaying = true;
};
_pause = function() {
audio.pause();
log("pause");
AudioStatus.isPlaying = false;
};
playPause = function() {
if (audio.paused) {
_play();
}
else {
_pause();
}
};
/* callback to set or update playback position */
updateProgress = function(value) {
audio.currentTime = value;
log("updateProgress");
};
};
the timer plays the sounds programmatically on the expiration. this works as long it is private. I did not understand why it has to be private.
Does it pass thru the if statement?
You could use ontimeupdate for placing the value of document.getElementById('siren').currentTime in a variable.
If set to more than 0, then you could update it in an if conditionnal.
All of the previous solutions are unacceptable because they download the same sound file for each time the sound is played! Do this instead, for the sake of simplicity and efficiency:
var sound = document.getElementById("mySound")
if(window.chrome){
sound = sound.cloneNode()
}
sound.play()
This is how I fixed the problem with chrome specifically.

How to pause streaming in soundcloud javascript api

I would like to allow a sound file to play and pause. The documentation shows how to play a streaming file:
$("#stream").live("click", function(){
SC.stream("/tracks/{'track-id'}", function(sound){
sound.play();
};
It uses Sound Manager to stream and uses some of it's objects and methods... like .pause()!
So here's the code i think should work:
var is_playing="false";
$("#stream").live("click", function(){
SC.stream("/tracks/{'track-id'}", function(sound){
if (is_playing==="true")
{
sound.pause();
is_playing = "false";
console.log(is_playing);
}
else if (is_playing === "false")
{
sound.play();
is_playing = "true";
console.log(is_playing);
}
});
However, it continues to play the track without pausing. Any ideas?
Thanks.
var is_playing = false;
soundManager.setup({
url: '/swf/soundmanager2.swf',
preferFlash: false,
onready: function() {
var mySound = soundManager.createSound({
id: 'aSound',
url: 'sonidos/sonido1.mp3' ,
autoplay: false
});
$("#stream").live("click", function(){
if (is_playing==false){
mySound.play();
is_playing = true;
}else if (is_playing== true) {
mySound.stop();
is_playing = false;
}
});
},
/* ontimeout: function() {
// Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.?
}*/
});
</script>
You have to use sound.stop();
There is also a built in function to toggle play/pause of a sound.
Use sound.togglePause(); to do that.
SC.stream("/tracks/13680213", function(sound) {
SC.sound = sound;
});
This means you aren't writing event listeners inside your SC.stream constructor then you can access the following (and more) at will:
SC.sound.play();
SC.sound.pause();
SC.sound.stop();
SC.sound.pause();
SC.sound.playState;
Since there are very few answers on this subject, I thought I would answer my own question.
I went ahead and downloaded Sound Manager 2 and placed the necessary files where they needed to be (you can find this in the basic tutorials section of the sound manager2 page.)
http://www.schillmania.com/projects/soundmanager2/demo/template/
The trick wass to locate the SoundCloud mp3 associated with the user I wanted to embed. To do this, I had to use a RESTClient and enter the appropriate api url.
It looks like this.
http://api.soundcloud.com/tracks/12758186.json?client_id={MyClient_ID_number}
The http://api.soundcloud.com/tracks/ is a general pointer to the track id="12758186". This is followed by the JSONP inclusion of my personal client_id to validate my request to the soundcloud server.
Once I had this url, I tried it in my browser and it redirected me to ** another url ** with an HTML5 mp3 player, which automatically played the song.
I got the idea to do this from this soundcloud doc:
http://developers.soundcloud.com/docs#playing
I then copied this url and mashed the code from my original question to the basic tutorial mentioned above (http://www.schillmania.com/projects/soundmanager2/demo/template/).
Final Code:
var is_playing = false;
$("#stream").live("click", function(){
soundManager.setup({
url: './swf/soundmanager2.swf',
onready: function() {
var mySound = soundManager.createSound({
id: 'aSound',
url: {**another url**},
autoplay: false
});
if (is_playing===false)
{
mySound.play();
is_playing = true;
}
else if (is_playing=== true)
{
mySound.stop();
is_playing = false;
}
},
ontimeout: function() {
// Hrmm, SM2 could not start. Missing SWF? Flash blocked? Show an error, etc.?
}
});
});
Simply link the event which you would like to trigger the pause function to the "sound" object which is passed into SC.stream()'s callback function.
The form in the following code accepts a sound cloud link such as this one: https://soundcloud.com/djalmix-1/living-in-stereo-dj-almix (so paste that in to the form once the app is live and click load). Also you must provide your own client_id that soundcloud gives you when you register your app, this takes only a minute or so.
<!DOCTYPE html>
<html>
<head></head>
<body>
<script src="http://connect.soundcloud.com/sdk.js"></script>
<script>
function load_sound() {
var track_url = document.getElementById("sc_url").value;
SC.initialize({
client_id: 'client_id'
});
SC.get('/resolve', {url: track_url}, function(track) {
console.log("the track id is: " + track.id);
SC.stream("/tracks/" + track.id, function(sound) {
var is_playing = true;
sound.play();
document.getElementById("stream").onclick = function(){
if(is_playing === false){
sound.resume();
is_playing = true;
} else if(is_playing === true){
sound.pause();
is_playing = false;
}
};
});
});
}
</script>
<form>
<input id="sc_url" type="url">
<input type="button" onclick="load_sound();" value="load">
</form>
<button id="stream">pause/resume</button>
</body>
</html>

Categories