You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Vue+Flask项目中Base64解码视频触发MEDIA_ERR_SRC_NOT_SUPPORTED错误求助

Vue+Flask项目中Base64解码视频触发MEDIA_ERR_SRC_NOT_SUPPORTED错误求助

大家好,我现在在排查一个Vue+Flask视频处理应用的问题,折腾了好几天没搞定,想请教下各位大佬的思路!

问题背景与现象

我做的是前端用Vue上传视频,后端Flask处理视频(转MP4+跑ML模型),最后返回包含处理后视频Base64、分析图Base64、结果文本的JSON。现在遇到的诡异问题是:

  • 用video.js播放解码后的视频时,直接触发了MEDIA_ERR_SRC_NOT_SUPPORTED错误(界面显示Video.js的报错提示)
  • 但同一份JSON里的JPG图片Base64却能完美解码显示(截图里的图表就是正常显示的那张图,忽略布局错乱的问题)

相关代码片段

Vue端上传视频的请求代码

async handleFileUpload($evt) {
  const file = $evt.target.files[0];

  if (file) {
    // VIDEO REQUEST
    const urlServer = "http://localhost:5000/analysis";
    const formData = new FormData();
    formData.append("file", file); // 'file'是后端接收的key

    (async () => {
      try {
        const result = await axios.post(urlServer, formData, {
          headers: { "Content-Type": "multipart/form-data" },
        });
        console.log(`RESULT`, result);
        const resultJSON = result.data;
        const strResult = resultJSON.string;
        const grafico_base64 = resultJSON.grafico;
        let video_base64 = resultJSON.video;
        console.log("RECEIVED VIDEO: ", video_base64, typeof video_base64);
        const extension = resultJSON.extVideo;

        const mimeVar = mime.lookup(extension);

        await db.open();
        const videoData = {
          string: strResult,
          video: video_base64,
          grafico: grafico_base64,
          mimeVideo: mimeVar,
        };
        console.log(videoData);
        let constId = await db.add(videoData);
        console.log(constId + " " + typeof constId);

        alert(constId);
        console.log("VIDEO PROCESSADO");
        this.$router.push({
          name: "analiseVideo",
          query: { idVideoAnalise: constId },
        });
      } catch (error) {
        console.error(error + "An error occurred while uploading the file.");
      }
    })();
  }
},

Vue端解码视频的代码

<script>
import db from "../db.js";
import videojs from "video.js";
import "video.js/dist/video-js.css";
import { Buffer } from "node:buffer";

export default {
  name: "Player_de_Video",
  components: {},
  data() {
    return {
      videoSource: "",
    };
  },
  async mounted() {
    console.log("MOUNTED VIDEOPLAYER:");
    const res = await this.pegarVideo();
    this.videoSource = res.videoURL;

    const mimeVideo = res.mime;
    this.graficoURL = res.graficoURL;
    this.$refs.imgGraf.src = this.graficoURL;
    this.strResult = res.strResult;

    const sources = [{ src: this.videoSource, type: `${mimeVideo}` }];
    this.setupPlayer(sources);
  },

  methods: {
    setupPlayer(sources) {
      //Initial videoplayer setup using data from VideoPlayer.vue
      this.player = videojs(this.$refs.videoplayer, {
        sources: sources,
      });
    },

    onVoltar() {
      this.$router.push("/");
    },
    async pegarVideo() {
      try {
        const resultData = await db.get(parseInt(this.$route.query.idVideoAnalise));
        const mime = resultData.mimeVideo;

        const videoURL = this.base64ToURL(resultData.video, mime, "video.mp4");
        console.log(`VIDEO URL: ${videoURL}`);
        const graficoURL = this.base64ToURL(resultData.grafico, "image/jpg");
        const strResult = resultData.string;

        return { strResult, graficoURL, mime, videoURL };
      } catch (error) {
        console.error("ERROR! " + error);
      }
    },
    base64ToURL(base64String, mimeType) {
      // Decode the Base64 string
      try {
        const binaryString = Buffer.from(base64String, "base64").toString("binary");
        console.log("base64 STRING: ", base64String);
        const len = binaryString.length;
        const bytes = new Uint8Array(len);
        for (let i = 0; i < len; i++) {
          bytes[i] = binaryString.charCodeAt(i);
        }
        const blob = new Blob([bytes], { type: String(mimeType) }); // Adjust the MIME type as needed
        
        // Generate a URL for the Blob and set it as the video source
        const url = URL.createObjectURL(blob);
        return url;
      } catch (error) {
        console.error("Error decoding Base64 string:", error);
        return null;
      }
    },
  }
};
</script>

我的排查思路(求补充!)

我已经试过检查前后端的Base64字符串是否一致,也确认了后端转码后的视频本地能正常播放,但就是前端解码后播放失败。有没有大佬遇到过类似的情况?为什么同一份JSON里的图片没问题,视频就不行呢?


可能的解决方案(来自社区经验)

我之前处理过类似的Base64视频播放问题,给你几个实测有效的思路:

1. 修复Base64转Blob的编码损耗问题

你当前用Buffer转二进制字符串再生成Uint8Array的方式,可能会因为编码兼容问题损坏视频数据。可以改成直接用浏览器原生API解码:

base64ToURL(base64String, mimeType) {
  try {
    // 先移除后端可能附带的data前缀(如果有的话)
    const pureBase64 = base64String.replace(/^data:.+;base64,/, '');
    // 直接用浏览器原生API解码Base64为二进制数组
    const byteChars = atob(pureBase64);
    const byteNumbers = new Array(byteChars.length);
    for (let i = 0; i < byteChars.length; i++) {
      byteNumbers[i] = byteChars.charCodeAt(i);
    }
    const byteArray = new Uint8Array(byteNumbers);
    const blob = new Blob([byteArray], { type: mimeType });
    return URL.createObjectURL(blob);
  } catch (error) {
    console.error("Error decoding Base64 string:", error);
    return null;
  }
}

2. 确认后端视频Base64的生成逻辑

  • 检查Flask后端生成视频Base64时,有没有添加data:video/mp4;base64,前缀,如果有,前端必须先移除前缀再解码
  • 后端转码后的视频,建议强制用H.264编码(浏览器兼容性最好的MP4编码格式),比如用FFmpeg转码时加上参数:-vcodec libx264 -acodec aac

3. 开启Video.js的Debug模式排查

初始化Video.js时开启debug模式,能拿到更详细的播放错误日志:

this.player = videojs(this.$refs.videoplayer, {
  sources: sources,
  controls: true,
  preload: 'auto',
  debug: true // 开启调试,控制台会输出详细的媒体加载日志
});

备注:内容来源于stack exchange,提问作者Luís Felipe Araujo de Oliveira

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 14:39:35