Android: URL.createObjectURL 无法正常工作(无法加载,因为未找到支持的源。)
Android: URL.createObjectURL does not work properly (Failed to load because no supported source was found.)
我正在尝试播放存储在我的 Meteor Android 应用程序的 LocalForage 中的音频文件。
LocalForage.getItem(track_id, (err, value)=>{
if(err)
throw err;
//the loaded value is an arraybuffer of an m4a file
let blob = new Blob([value]);
let url = (window.URL || window.webkitURL || window || {}).createObjectURL(blob);
let testAudio = new Audio(url);
testAudio.play().then(()=>{console.log("play successful")}).catch((err)=>{console.error(err)});
});
之前,我将 url 传递给 Howler.js 的实例,但为了更容易理解发生了什么,我添加了 testAudio。
在浏览器中测试 (Chrome) 时,代码可以正常工作。 url 已创建,音频正在播放。
Android(使用 Chromium 作为所有 Meteor Android 应用程序)但是,似乎不喜欢我的方法:
创建对象 URL 时,Chromium returns 一个 URL 像这样:
blob:http%3A//localhost%3A12128/4de4516a-2989-4e99-9269-0beff4517fc4
如你所见,这不是一个可用的URL,即使我这样做
url = url.replace(/%3A/g, ':');
最终的控制台输出是
DOMException: Failed to load because no supported source was found.
有谁知道为什么这对 Android 不起作用?我在这里查看了具有相同问题的其他问题,但我的代码对我来说是正确的并且在 Chrome 中测试时有效,所以我真的不知道如何解决这个问题。
顺便说一下,Audiobuffer 是这样保存的:
const request = new window.XMLHttpRequest();
request.addEventListener('readystatechange', () => {
if (request.readyState === 4) {
LocalForage.setItem(track.file_id, request.response, (err, value) => {
console.log('Successfully saved to locale forage: ' + track.name);
})
}
});
request.open('GET', track.audioLink, true);
request.responseType = 'arraybuffer';
request.send();
我 运行 不久前进入了类似的东西,并使用了这个解决方法(在 this chromium 问题中找到)
你也许可以做类似的事情
let url = (window.URL || window.webkitURL || window || {}).createObjectURL(blob);
// workaround for mobile playback, where it didn't work on chrome/android.
// fetch blob at url using xhr, and use url generated from that blob.
// see issue: https://code.google.com/p/chromium/issues/detail?id=227476
// thanks, gbrlg
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status == 200) {
var url = (window.URL || window.webkitURL || window || {}).createObjectURL(xhr.response);
// now url is ready
}
};
xhr.send();
基本上,在您创建 blob url 之后,您再次使用 XHR 获取它,然后它就可以工作了。
它一点也不漂亮,但也许您遇到了这个错误。我在 open source project 中成功使用了此解决方法,但就像我在评论中提到的那样,如果没记错的话,它只适用于 Android 5+。
我正在尝试播放存储在我的 Meteor Android 应用程序的 LocalForage 中的音频文件。
LocalForage.getItem(track_id, (err, value)=>{
if(err)
throw err;
//the loaded value is an arraybuffer of an m4a file
let blob = new Blob([value]);
let url = (window.URL || window.webkitURL || window || {}).createObjectURL(blob);
let testAudio = new Audio(url);
testAudio.play().then(()=>{console.log("play successful")}).catch((err)=>{console.error(err)});
});
之前,我将 url 传递给 Howler.js 的实例,但为了更容易理解发生了什么,我添加了 testAudio。
在浏览器中测试 (Chrome) 时,代码可以正常工作。 url 已创建,音频正在播放。
Android(使用 Chromium 作为所有 Meteor Android 应用程序)但是,似乎不喜欢我的方法: 创建对象 URL 时,Chromium returns 一个 URL 像这样:
blob:http%3A//localhost%3A12128/4de4516a-2989-4e99-9269-0beff4517fc4
如你所见,这不是一个可用的URL,即使我这样做
url = url.replace(/%3A/g, ':');
最终的控制台输出是
DOMException: Failed to load because no supported source was found.
有谁知道为什么这对 Android 不起作用?我在这里查看了具有相同问题的其他问题,但我的代码对我来说是正确的并且在 Chrome 中测试时有效,所以我真的不知道如何解决这个问题。
顺便说一下,Audiobuffer 是这样保存的:
const request = new window.XMLHttpRequest();
request.addEventListener('readystatechange', () => {
if (request.readyState === 4) {
LocalForage.setItem(track.file_id, request.response, (err, value) => {
console.log('Successfully saved to locale forage: ' + track.name);
})
}
});
request.open('GET', track.audioLink, true);
request.responseType = 'arraybuffer';
request.send();
我 运行 不久前进入了类似的东西,并使用了这个解决方法(在 this chromium 问题中找到)
你也许可以做类似的事情
let url = (window.URL || window.webkitURL || window || {}).createObjectURL(blob);
// workaround for mobile playback, where it didn't work on chrome/android.
// fetch blob at url using xhr, and use url generated from that blob.
// see issue: https://code.google.com/p/chromium/issues/detail?id=227476
// thanks, gbrlg
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status == 200) {
var url = (window.URL || window.webkitURL || window || {}).createObjectURL(xhr.response);
// now url is ready
}
};
xhr.send();
基本上,在您创建 blob url 之后,您再次使用 XHR 获取它,然后它就可以工作了。
它一点也不漂亮,但也许您遇到了这个错误。我在 open source project 中成功使用了此解决方法,但就像我在评论中提到的那样,如果没记错的话,它只适用于 Android 5+。