javascript HTML5 音频 - 为什么不能在 iOS 上工作?(不涉及自动播放)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25023211/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTML5 Audio - Why not working on iOS? (NO autoplay involved)
提问by Christian
I built a simple demo app to test HTML5-Audio. When you touch or click the robot's head the webapp says"eins", which is german for "one" (I had this soundfile on my computer for testing).
我构建了一个简单的演示应用程序来测试 HTML5-Audio。当你触摸或点击机器人的头部webapp的说:“EINS”,这是德国的“一”(我有这个音效档我的电脑上测试)。
You can test the demo app here: http://jstesproject.cwsurf.de/
您可以在此处测试演示应用程序:http: //jstesproject.cwsurf.de/
(Remarks: The robot is the phonegap icon, but there is NO phonegap or cordova technology involved. It is plain HTML5, Javascript (+jQuery) and CSS. Also, you have manually click the robot's head, so there is NO autostart involved.)
(备注:机器人是phonegap图标,但不涉及phonegap或cordova技术。它是纯HTML5,Javascript(+jQuery)和CSS。另外,你手动点击了机器人的头部,所以不涉及自动启动。 )
The webapp works fine on desktop browsers (I tested Chrome and Firefox) and on Android native browser (I tested with Android 4.0). However, I cannot get it to work under iOS (iPhone, neither Chrome nor Safari). The Audio-Object throws an error (code 4).
webapp 在桌面浏览器(我测试了 Chrome 和 Firefox)和 Android 原生浏览器(我用 Android 4.0 测试)上运行良好。但是,我无法让它在 iOS(iPhone,Chrome 和 Safari 都不是)下运行。音频对象引发错误(代码 4)。
Why is this? How can I get it to work under iOS?There is no autostart involved. Please see my code below:
为什么是这样?我怎样才能让它在iOS下工作?不涉及自动启动。请看我下面的代码:
Code
代码
$(document).ready(function() {
clearLog();
log('Document ready!');
$('.clickable').click(function() {
var value = $(this).html();
playAudio('res/audio/', '1.wav');
});
});
//==============
// AUDIO
function playAudio(path, src) {
log('playAudio called! Arguments: ' + path + ', ' + src);
$('#path').html('path -> ' + path);
$('#file').html('file -> ' + path + src);
if (typeof Audio != "undefined") {
log('Playing Audio using HTML5...');
var audioUrl = path + src;
log('audioUrl: ' + audioUrl);
var audio = new Audio();
audio.src = audioUrl;
audio.type = 'audio/x-wav';
audio.addEventListener('error', function() {
log('Audio error: ' + audioUrl + '; ' + JSON.stringify(audio.error));
$('#audioStatus').html('Audio error: ' + audioUrl + '; ' + JSON.stringify(audio.error));
});
audio.addEventListener('play', function() {
log('Starting audio: ' + audioUrl + '; MIME-type: ' + audio.type);
$('#audioStatus').html('Playing audio: ' + audioUrl);
});
audio.addEventListener('ended', function() {
log('Playback ended: ' + audioUrl);
$('#audioStatus').html('Stopped...');
});
audio.addEventListener('canplay', function() {
audio.play();
});
} else {
log('Cannot play audio via HTML5 -> !(typeof Audio != "undefined")');
}
}
//==============
// UTILS
function log(s, showAlert) {
var now = new Date();
var text = makeTwoDigits(now.getHours()) + ':' + makeTwoDigits(now.getMinutes()) + ':' + makeTwoDigits(now.getSeconds()) + ' >> ' + s;
$('#console').append('<p>' + text + '</p>');
console.log(text);
if (showAlert) {
alert(text);
}
}
function clearLog() {
$('#console').html('<p><strong>Console</strong> <span>[clear]</span></p>');
$('#console span').click(function() {
clearLog();
});
}
function makeTwoDigits(x) {
if (x < 10) {
return '0' + x;
} else {
return '' + x;
}
}
{
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
overflow-y: scroll;
background-color: #EEE;
}
.clickable {
cursor: pointer;
}
.icon {
text-align: center;
}
.app {
width: 256px;
height: auto;
margin: 50px auto;
padding: 20px;
background: linear-gradient(#9dd2ea, #8bceec);
border-radius: 10px;
}
.numbers,
.display {
overflow: hidden;
}
.app .numbers span {
float: left;
width: 50px;
height: 50px;
background: white;
border-radius: 10px;
padding: 10px;
margin: 10px;
line-height: 32px;
text-align: center;
cursor: pointer;
}
.app .display span {
float: left;
width: 190px;
height: 50px;
background: grey;
color: white;
border-radius: 10px;
padding: 10px;
margin: 10px;
line-height: 32px;
text-align: center;
cursor: pointer;
}
.app .debug {
text-align: center;
margin-top: 10px;
}
#console {
width: 80%;
margin: 20px auto;
padding: 20px;
background: linear-gradient(#9dd2ea, #00d3ec);
border-radius: 10px;
}
#console p {
margin: 10px 0px;
}
#console span {
float: right;
cursor: pointer;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="css/index.css" />
<title>I can say one!</title>
</head>
<body>
<div class="app">
<div class="clickable icon">CLICK MY ROBOT-HEAD!</div>
<div class="clickable icon">
<img src="icon.png" />
</div>
<div class="debug">Info:</div>
<div id="path" class="debug">N/A</div>
<div id="file" class="debug">N/A</div>
<div id="audioStatus" class="debug">N/A</div>
</div>
<div id="console">
<p><strong>Console</strong> <span>[clear]</span>
</p>
</div>
<script src="js/jquery-2.1.1.min.js" type="text/javascript"></script>
<script src="js/prefixfree-1.0.7.js" type="text/javascript"></script>
<script src="js/index.js" type="text/javascript"></script>
</body>
</html>
回答by idbehold
Move the call to audio.play()
outside the "canplay" event listener. To play audio/video on mobile devices you need direct, physical and synchronousinteraction from the user. You nailed the first two, but when you put that audio.play()
inside the event listener you break the synchronous requirement.
将调用移到audio.play()
“canplay”事件侦听器之外。要在移动设备上播放音频/视频,您需要来自用户的直接、物理和同步交互。您确定了前两个,但是当您将其audio.play()
放入事件侦听器时,您就打破了同步要求。
// BEFORE
audio.addEventListener('canplay', function() {
audio.play();
});
// AFTER
audio.play();