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

寻求基于Expo CLI的React Native录音可视化实现方案

Expo CLI 实现 React Native 录音可视化方案

核心依赖选择

无需 eject,直接基于 Expo 官方生态实现:

  • expo-av:Expo 官方音频录制/播放库,支持实时获取音频振幅、频谱数据
  • react-native-svg:用来绘制波形、频谱类可视化图形(Expo 已内置基础支持,安装即可用)

步骤1:安装依赖

expo install expo-av react-native-svg

步骤2:基础波形可视化实现

利用 Audio.Recording 的进度监听获取实时振幅,再通过 SVG 绘制动态波形:

import { Audio } from 'expo-av';
import { useState, useEffect } from 'react';
import { View, Button } from 'react-native';
import Svg, { Rect } from 'react-native-svg';

export default function AudioWaveVisualizer() {
  const [recording, setRecording] = useState(null);
  const [amplitude, setAmplitude] = useState(0);

  // 申请录音权限
  useEffect(() => {
    async function requestAudioPermission() {
      const { status } = await Audio.requestPermissionsAsync();
      if (status !== 'granted') {
        alert('需授予录音权限才能使用该功能');
      }
    }
    requestAudioPermission();
  }, []);

  // 启动录音并监听振幅
  async function startRecording() {
    try {
      await Audio.setAudioModeAsync({
        allowsRecordingIOS: true,
        playsInSilentModeIOS: true,
      });

      const newRecording = new Audio.Recording();
      await newRecording.prepareToRecordAsync(Audio.RECORDING_OPTIONS_PRESET_HIGH_QUALITY);
      await newRecording.startAsync();

      // 实时获取音频振幅(范围0-1)
      newRecording.addProgressListener((data) => {
        setAmplitude(data.metering.average);
      });

      setRecording(newRecording);
    } catch (err) {
      console.error('录音启动失败:', err);
    }
  }

  // 停止录音
  async function stopRecording() {
    if (!recording) return;
    try {
      await recording.stopAndUnloadAsync();
      setRecording(null);
      setAmplitude(0);
    } catch (err) {
      console.error('录音停止失败:', err);
    }
  }

  // 绘制动态柱状波形
  const renderWaveBar = () => {
    // 将0-1的振幅映射为0-200的柱子高度
    const barHeight = Math.max(10, amplitude * 200);
    return (
      <Svg width="320" height="220" viewBox="0 0 320 220">
        <Rect
          x="60"
          y={220 - barHeight}
          width="200"
          height={barHeight}
          fill="#2196F3"
          rx="8"
        />
      </Svg>
    );
  };

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center', gap: 24 }}>
      {renderWaveBar()}
      <Button
        title={recording ? '停止录音' : '开始录音'}
        onPress={recording ? stopRecording : startRecording}
      />
    </View>
  );
}

进阶:频谱可视化

如果需要更精细的频谱图,可使用 Audio.Analyser 获取多频段能量数据:

// 在startRecording函数中添加分析器
const analyser = new Audio.Analyser({
  recording: newRecording,
  fftSize: 256, // FFT尺寸越大,频谱数据点越多(可选值:32/64/128/256等)
});

// 定时获取频谱数据(每50ms更新一次)
const spectrumInterval = setInterval(() => {
  const frequencyData = analyser.getByteFrequencyData();
  // frequencyData为Uint8Array,每个元素对应一个频段的能量值(0-255)
  setSpectrumData([...frequencyData]);
}, 50);

// 停止录音时清除定时器
async function stopRecording() {
  if (!recording) return;
  clearInterval(spectrumInterval);
  // ...其余停止录音逻辑
}

注意事项

  • 振幅值默认范围为0-1,需根据需求映射为可视化元素的尺寸
  • iOS/Android 权限逻辑略有差异,必须先申请权限再启动录音
  • 避免过于频繁的状态更新,可调整监听/定时器的时间间隔以优化性能

内容的提问来源于stack exchange,提问作者Doğa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 12:00:58