safari video元素标签不支持blob解决办法

1,193 阅读1分钟

背景

在做需求的时候,都开发完成了,自测兼容性的时候,发现safari的video却不能正常运行,在控制台中输入video.error,发现报错了,我得blob地址放入<video />src 其他浏览器都正常,为什么就safari不支持呢?于是想办法处理

排查

使用的safari是最新版的Mac系统13.3.1

做了以下排查测试:

  1. <video />src更换为http协议的mp4地址,可以正常播放
  2. 能第1点的静态资源mp4转为blob之后,放入<video />src,不能正常播放
  3. 本地静态资源放入<video />src,能正常播放

说明:safari的<video />不能支持blob类型的src

再查查一下webkit的bugIssue

image.png 在海外论坛逛了几圈,发现确实是兼容性问题

解决方法

传入<video />src只要是mp4类型的blob就行了

代码部分:

如果还没转为blob,那么就成blob

/**
 * 将链接地址字符内容转变成 Blob 地址
 * @param {string} url - 资源下载地址
 * @returns {Promise<string>} 包含 Blob 地址的 Promise 对象
 */
export const urlDownload2Blob = async (url) => {
  try {
    const res = await fetch(url);
    if (res.status !== 200) {
      throw new Error('Request failed');
    }
    const arrayBuffer = await res.arrayBuffer();
    // 兼容 Safari,Safari 无法将非 'video/mp4' 的 Blob 传入 video src
    const blob = new Blob([arrayBuffer], { type: 'video/mp4' });
    // 兼容 Safari
    window.URL = window.URL || window.webkitURL;
    // 将链接地址字符内容转变成 Blob 地址
    const blobUrl = window.URL.createObjectURL(blob);
    return blobUrl;
  } catch (error) {
    throw new Error('Failed to convert URL to Blob');
  }
};

如果已经是blob了,那么就对blob进行类型转换

/**
 * 将 Blob 地址转换为 MP4 类型的 Blob 对象
 * @param {string} blobUrl - Blob 地址
 * @returns {Promise<Blob>} 转换后的 MP4 类型的 Blob 对象
 */
const blobUrlToMP4Blob = async (blobUrl) => {
  try {
    const response = await fetch(blobUrl);
    const arrayBuffer = await response.arrayBuffer();
    const mp4Blob = new Blob([arrayBuffer], { type: 'video/mp4' });

    return mp4Blob;
  } catch (error) {
    throw new Error('Failed');
  }
};