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

如何在Ruby on Rails中集成WhatsApp式语音录制聊天功能?

嘿,我刚好折腾过类似的功能!结合Web Audio相关的录制能力,在Rails里实现WhatsApp风格的语音消息其实可以拆成几个核心步骤,一步步来就很清晰:

1. 前端实现语音录制与本地处理

首先搞定用户端的录制逻辑,这里推荐用现代的MediaRecorder API(比早期的Web Audio API示例更简洁,浏览器支持也更友好):

  • 先获取麦克风权限,创建录制实例,监听录制过程中的数据片段,停止时生成音频Blob:
// 全局变量存录制实例,方便后续停止
let currentRecorder = null;

async function startRecording() {
  try {
    // 请求麦克风权限
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    currentRecorder = new MediaRecorder(stream);
    const audioChunks = [];

    // 收集录制的音频片段
    currentRecorder.addEventListener("dataavailable", (event) => {
      audioChunks.push(event.data);
    });

    // 录制停止后处理Blob
    currentRecorder.addEventListener("stop", () => {
      const audioBlob = new Blob(audioChunks, { type: "audio/webm" });
      // 生成预览URL,让用户试听
      const previewUrl = URL.createObjectURL(audioBlob);
      // 绑定到页面的audio标签上,让用户确认
      document.getElementById("preview-audio").src = previewUrl;
      // 缓存Blob,等待发送
      window.pendingAudioBlob = audioBlob;
    });

    currentRecorder.start();
    // 更新UI,显示录制状态
    document.getElementById("record-btn").textContent = "停止录制";
  } catch (err) {
    console.error("麦克风权限被拒绝或录制失败:", err);
  }
}

function stopRecording() {
  if (currentRecorder) {
    currentRecorder.stop();
    // 关闭媒体流,释放麦克风
    currentRecorder.stream.getTracks().forEach(track => track.stop());
    currentRecorder = null;
    document.getElementById("record-btn").textContent = "开始录制";
  }
}
  • 补充UI:页面上放置录制按钮、预览音频标签和发送按钮,让用户确认录制内容后再发送。
2. Rails后端处理音频存储与消息创建

用Rails自带的Active Storage来处理音频文件存储是最省心的,它支持本地磁盘、S3、阿里云OSS等多种存储后端:

  1. 先确保Active Storage已配置:
rails active_storage:install
rails db:migrate
  1. 在你的聊天消息模型(比如Message)中关联音频附件:
# app/models/message.rb
class Message < ApplicationRecord
  belongs_to :sender, class_name: "User"
  belongs_to :chat_room
  # 关联音频附件
  has_one_attached :audio_file
end
  1. 写一个处理消息创建的控制器方法,接收前端传来的音频Blob:
# app/controllers/messages_controller.rb
class MessagesController < ApplicationController
  before_action :authenticate_user!

  def create
    @chat_room = ChatRoom.find(params[:message][:chat_room_id])
    @message = current_user.messages.new(message_params)

    if @message.save
      # 通过Action Cable把消息推送给聊天室里的其他用户
      ChatRoomChannel.broadcast_to(
        @chat_room,
        message: render_to_string(partial: "messages/message", locals: { message: @message })
      )
      head :ok
    else
      render json: { errors: @message.errors.full_messages }, status: :unprocessable_entity
    end
  end

  private

  def message_params
    params.require(:message).permit(:chat_room_id, :audio_file)
  end
end
  1. 前端发送音频的函数,用FormData来传递Blob:
function sendAudioMessage() {
  if (!window.pendingAudioBlob) return;

  const formData = new FormData();
  formData.append("message[chat_room_id]", currentChatRoomId); // 替换成你的当前聊天室ID
  // 给音频文件命名,方便后端识别
  formData.append("message[audio_file]", window.pendingAudioBlob, `voice-${Date.now()}.webm`);

  fetch("/messages", {
    method: "POST",
    headers: {
      "X-CSRF-Token": document.querySelector('meta[name="csrf-token"]').content
    },
    body: formData
  }).then(() => {
    // 发送完成后清空缓存的Blob
    window.pendingAudioBlob = null;
    document.getElementById("preview-audio").src = "";
  });
}
3. Action Cable实时推送音频消息

当后端保存好消息和音频附件后,通过Action Cable把消息广播给聊天室的其他用户,对方前端收到后渲染音频播放器:

在消息的partial视图(比如app/views/messages/_message.html.erb)中,添加音频播放控件:

<div class="message <%= message.sender == current_user ? 'sent' : 'received' %>">
  <% if message.audio_file.attached? %>
    <div class="audio-container">
      <audio controls class="audio-player">
        <source src="<%= rails_blob_url(message.audio_file) %>" type="audio/webm">
        你的浏览器不支持音频播放,请升级浏览器。
      </audio>
      <!-- 可添加音频时长显示,需前端计算或后端存储 -->
    </div>
  <% else %>
    <!-- 文本消息的渲染 -->
    <p><%= message.content %></p>
  <% end %>
</div>
4. 额外优化建议
  • 格式兼容:WebM格式在现代浏览器没问题,但如果要兼容更多设备,可以用streamio-ffmpeg gem在后端把音频转成MP3格式,在Message模型的after_save回调里处理转换逻辑。
  • 录制体验:添加录制时长显示、录制时的声波动画,让用户更直观地感知录制状态。
  • 进度提示:发送音频时显示上传进度,提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:25:01