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

WhatsApp API语音消息下载代理端点异常:音频无法播放问题

排查WhatsApp Cloud API媒体代理端点音频无法播放的问题

问题分析

直接请求WhatsApp媒体URL能正常播放音频,但通过代理端点获取并保存的音频无法播放,核心问题大概率出在二进制数据处理、请求重定向处理或响应头传递环节,以下是具体排查和修复方案:

可能的问题点及修复步骤

1. 未跟随重定向

WhatsApp的媒体URL可能返回302跳转,默认request库可能不自动跟随重定向,导致获取的不是实际音频数据。

  • 修复:在请求配置中添加重定向跟随设置
request.get(
  {
    url: url,
    headers: {
      Authorization: `Bearer ${process.env.AUTH_TOKEN}`,
      Accept: 'audio/ogg',
    },
    encoding: null,
    followRedirect: true, // 开启自动跟随重定向
    maxRedirects: 5, // 设置最大重定向次数
  },
  // 后续回调逻辑
);

2. 二进制文件写入编码错误

代码中写入文件时指定了'binary'编码,但encoding: null已将响应转为Buffer,额外指定编码会导致数据损坏。

  • 修复:移除写入文件时的编码参数
// 原代码
fs.writeFile(filePath, body, 'binary', (writeErr) => { ... })

// 修改后
fs.writeFile(filePath, body, (writeErr) => { ... })

3. 重复读写文件引入的风险

先写入本地再通过res.download读取返回,多了一次IO操作,可能引入文件读取错误。可以直接将获取到的Buffer返回给客户端,同时保存文件。

  • 修复:替换res.download为直接发送Buffer,并传递正确的响应头
// 替换res.download逻辑
res.setHeader('Content-Type', resp.headers['content-type'] || 'audio/ogg');
res.setHeader('Content-Disposition', `attachment; filename="downloaded_audio.ogg"`);
res.send(body);

4. 缺少参数校验与错误状态码处理

原代码未校验url参数是否存在,也未处理WhatsApp返回的非200状态码,容易隐藏问题。

  • 修复:添加参数校验和状态码判断
exports.downLoadMedia = (req, res) => {
  const url = req.query.url;
  if (!url) {
    return res.status(400).json({ error: "Missing media URL parameter" });
  }

  request.get(/* ... */, function (err, resp, body) {
    if (err) {
      console.error("Request error:", err);
      return res.status(500).json({ error: "Failed to fetch media" });
    }

    // 检查WhatsApp返回的状态码
    if (resp.statusCode !== 200) {
      console.error("Media fetch failed with status:", resp.statusCode, resp.body.toString());
      return res.status(resp.statusCode).json({ error: "Failed to fetch media from WhatsApp" });
    }

    // 后续文件保存和响应逻辑
  });
};

完整修复后的代码

const request = require('request');
const path = require('path');
const fs = require('fs');

exports.downLoadMedia = (req, res) => {
  const url = req.query.url;
  if (!url) {
    return res.status(400).json({ error: "Missing media URL parameter" });
  }

  request.get(
    {
      url: url,
      headers: {
        Authorization: `Bearer ${process.env.AUTH_TOKEN}`,
        Accept: 'audio/ogg',
      },
      encoding: null,
      followRedirect: true,
      maxRedirects: 5,
    },
    function (err, resp, body) {
      if (err) {
        console.error("Request error:", err);
        return res.status(500).json({ error: "Failed to fetch media" });
      }

      if (resp.statusCode !== 200) {
        console.error("Media fetch failed with status:", resp.statusCode, resp.body.toString());
        return res.status(resp.statusCode).json({ error: "Failed to fetch media from WhatsApp" });
      }

      const fileName = 'downloaded_audio.ogg';
      const filePath = path.join(__dirname, fileName);

      fs.writeFile(filePath, body, (writeErr) => {
        if (writeErr) {
          console.error("File write error:", writeErr);
          // 即使保存失败,优先返回音频给客户端
          res.setHeader('Content-Type', resp.headers['content-type'] || 'audio/ogg');
          res.setHeader('Content-Disposition', `attachment; filename="downloaded_audio.ogg"`);
          return res.send(body);
        }

        // 直接返回原始Buffer
        res.setHeader('Content-Type', resp.headers['content-type'] || 'audio/ogg');
        res.setHeader('Content-Disposition', `attachment; filename="downloaded_audio.ogg"`);
        res.send(body);
      });
    }
  );
};

额外排查建议

  • 对比直接请求和代理返回的文件大小,若不一致说明数据传输过程中损坏
  • 使用ffmpeg -i downloaded_audio.ogg检查文件是否为有效OGG格式,报错则说明文件已损坏
  • 查看控制台日志,确认是否有请求错误或非200状态码返回

内容的提问来源于stack exchange,提问作者Davia

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 00:45:27