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

Flutter技术问题:如何将flutter_sound录制的音频发送至Socket服务器

Flutter语音消息实现:获取音频信息并通过Socket发送

1. 获取音频文件信息

基础文件属性(大小、路径)

用Dart内置的dart:io库直接读取文件核心属性:

import 'dart:io';

// recordedFilePath 是flutter_sound返回的音频文件路径
final audioFile = File(recordedFilePath);

// 获取文件大小(单位:字节)
final int fileSize = await audioFile.length();
// 获取文件最后修改时间
final DateTime modifiedTime = await audioFile.lastModified();

音频元数据(时长、编码格式)

如果需要音频时长这类专业信息,推荐用flutter_sound自带的工具类,无需额外依赖:

import 'package:flutter_sound/flutter_sound.dart';

// 获取音频时长(返回Duration类型)
final Duration? audioDuration = await FlutterSoundHelper().duration(recordedFilePath);
print('音频时长:${audioDuration?.inSeconds}秒');

若需更详细的元数据(如编码格式、采样率),可使用audio_metadata第三方库,添加依赖后调用:

import 'package:audio_metadata/audio_metadata.dart';

final metadata = await MetadataRetriever.fromFile(audioFile);
print('编码格式:${metadata.format}');
print('采样率:${metadata.sampleRate}');

2. 通过socket_io_client发送音频到服务器

方案1:直接发送二进制字节(推荐短语音场景)

读取文件字节后,将音频数据与元数据一起通过Socket发送:

import 'dart:io';
import 'package:socket_io_client/socket_io_client.dart' as IO;

// 初始化Socket连接(确保已完成配置)
final IO.Socket socket = IO.io('http://localhost:3000', {
  'transports': ['websocket'],
  'autoConnect': true,
});

// 读取音频文件字节
final List<int> audioBytes = await audioFile.readAsBytes();

// 发送语音消息事件
socket.emit('voice_message', {
  'senderId': '当前用户ID',
  'duration': audioDuration?.inSeconds,
  'fileSize': fileSize,
  'audioData': audioBytes,
  'fileName': 'voice_${DateTime.now().millisecondsSinceEpoch}.aac', // 自定义唯一文件名
});

方案2:分块发送(大音频场景)

如果音频文件较大,可拆分字节分块发送,避免单次发送数据过大:

const int chunkSize = 1024 * 100; // 100KB每块
int offset = 0;
final String messageId = DateTime.now().millisecondsSinceEpoch.toString();

while (offset < audioBytes.length) {
  final end = offset + chunkSize > audioBytes.length ? audioBytes.length : offset + chunkSize;
  final chunk = audioBytes.sublist(offset, end);
  
  socket.emit('voice_chunk', {
    'messageId': messageId,
    'chunk': chunk,
    'isLast': end == audioBytes.length,
    'metadata': {
      'senderId': '当前用户ID',
      'duration': audioDuration?.inSeconds,
      'fileName': 'voice_${messageId}.aac',
    }
  });
  
  offset += chunkSize;
}

3. 服务器端接收处理(Node.js示例)

假设你的Socket服务器用Node.js的socket.io搭建,接收并保存音频:

const fs = require('fs');
const path = require('path');
const http = require('http');
const express = require('express');
const { Server } = require('socket.io');

const app = express();
const server = http.createServer(app);
const io = new Server(server, {
  cors: { origin: '*' } // 开发环境临时放开,生产环境需限制域名
});

// 配置静态文件服务,让客户端能访问保存的音频
app.use('/voices', express.static(path.join(__dirname, 'voices')));

// 创建保存音频的目录(不存在则自动创建)
if (!fs.existsSync('./voices')) fs.mkdirSync('./voices');

io.on('connection', (socket) => {
  // 接收完整语音消息
  socket.on('voice_message', (data) => {
    const filePath = path.join(__dirname, 'voices', data.fileName);
    // 将二进制数据写入文件
    fs.writeFileSync(filePath, Buffer.from(data.audioData));
    
    // 转发给其他在线用户
    socket.broadcast.emit('receive_voice', {
      senderId: data.senderId,
      duration: data.duration,
      audioUrl: `http://localhost:3000/voices/${data.fileName}`
    });
  });

  // 接收分块语音(如果用分块方案)
  const chunkCache = {};
  socket.on('voice_chunk', (data) => {
    const { messageId, chunk, isLast, metadata } = data;
    if (!chunkCache[messageId]) {
      chunkCache[messageId] = { chunks: [], metadata };
    }
    chunkCache[messageId].chunks.push(chunk);
    
    if (isLast) {
      const allBytes = Buffer.concat(chunkCache[messageId].chunks);
      const filePath = path.join(__dirname, 'voices', metadata.fileName);
      fs.writeFileSync(filePath, allBytes);
      
      // 转发完整语音信息
      socket.broadcast.emit('receive_voice', {
        senderId: metadata.senderId,
        duration: metadata.duration,
        audioUrl: `http://localhost:3000/voices/${metadata.fileName}`
      });
      delete chunkCache[messageId];
    }
  });
});

server.listen(3000, () => console.log('服务器运行在3000端口'));

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 18:10:27