@audiowave/react

中文文档
0.6.2发布于 2025/10/31MITTypeScriptESM + CJS近 30 天下载 78.4万

反射音频可视化组件

中文使用文档
文档目录27 节
  1. 启发和关键差异
  2. 安装
  3. 快速启动
  4. API 参考
  5. 音频窗口组件
  6. 使用MediaAudio Hook( 建议)
  7. 使用Audio Source Hook( 语言)
  8. 专用钩子
  9. 使用 CustomAudio Hook 软件
  10. 电子融合指南
  11. 最佳做法:主要进程音频处理
  12. 可视化控制
  13. 使用参考文献( 模拟)
  14. 使用道具( 声明)
  15. 高度计算模式
  16. 峰值模式( 默认)
  17. RMS 模式( 实际声音)
  18. 适应模式( 动态缩放)
  19. 模式切换示例
  20. 最佳做法
  21. 处理错误
  22. 重要使用说明
  23. 性能优化
  24. 响应设计
  25. 类型脚本支持
  26. 浏览器支持
  27. 许可证

@ audiowave/反应

用于实时音频可视化的轻量级 React 组件

启发和关键差异

这个项目的灵感来自 反应-视听器 但采取不同、更有重点的办法:

是什么让我们不同:

  • 只可视化 - 没有内置播放或记录功能
  • 无控制按钮 - 纯可视化组件,无UI控制
  • 轻巧 - 有重点特性集的最小捆绑大小
  • 简单整合 - 投放现有音频应用程序而不发生冲突
  • 弹性 - 使用你提供的任何音频源

适合这些情景:

  • 现有音频应用程序 - 在已经处理音频的应用程序中添加可视化
  • 记录软件 - 可视化麦克风输入而不发生音频冲突
  • 音乐播放器 - 在音频/视频播放中添加波形
  • 自定义音频工作流程 - 与任何音频来源或处理管道相结合
  • 轻量级项目 - 最小捆绑大小,只需要可视化

安装

npm install @audiowave/react

快速启动

用麦克风输入的基本用途 :

import { AudioWave, useMediaAudio } from '@audiowave/react';
import { useRef, useState, useMemo, useCallback } from 'react';

export default function App() {
  const [mediaStream, setMediaStream] = useState<MediaStream | null>(null);
  const [isRecording, setIsRecording] = useState(false);

  // AudioWave handles visualization, you control the audio source
  // Note: For dynamic audio sources, memoize the options object (see Important Usage Notes)
  const handleError = useCallback((error: Error) => {
    console.error('Audio error:', error);
  }, []);

  const audioOptions = useMemo(() => ({
    source: mediaStream,
    onError: handleError,
  }), [mediaStream, handleError]);

  const { source, error } = useMediaAudio(audioOptions);
  const audioWaveRef = useRef<AudioWaveController>(null);

  const startRecording = async () => {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    setMediaStream(stream);
    setIsRecording(true);
  };

  const stopRecording = () => {
    mediaStream?.getTracks().forEach(track => track.stop());
    setMediaStream(null);
    setIsRecording(false);
  };

  return (
    <div>
      {error && <div>Error: {error.message}</div>}
      <AudioWave ref={audioWaveRef} source={source} height={100} />

      {/* You provide the controls - AudioWave just visualizes */}
      <button onClick={isRecording ? stopRecording : startRecording}>
        {isRecording ? 'Stop Recording' : 'Start Recording'}
      </button>

      {/* Optional: Control visualization display */}
      <button onClick={() => audioWaveRef.current?.pause()}>Pause Waveform</button>
      <button onClick={() => audioWaveRef.current?.resume()}>Resume Waveform</button>
      <button onClick={() => audioWaveRef.current?.clear()}>Clear Waveform</button>
    </div>
  );
}

工作与任何音频源 :

// With audio file
const audioElement = useRef<HTMLAudioElement>(null);
const { source } = useAudioSource({ source: audioElement.current });

// With video file
const videoElement = useRef<HTMLVideoElement>(null);
const { source } = useAudioSource({ source: videoElement.current });

// With Web Audio API nodes
const { source } = useAudioSource({ source: audioNode });

// With custom audio data (Electron, Node.js, etc.)
const { source } = useCustomAudio();

API 参考

音频窗口组件

主要可视化组件 - 纯显示,无音频控制.

<AudioWave
  // === AUDIO SOURCE ===
  source={source}            // AudioSource from useAudioSource

  // === DIMENSIONS ===
  width="100%"               // Component width (string | number)
  height={200}               // Component height in pixels

  // === VISUAL STYLING ===
  backgroundColor="transparent" // Background color
  barColor="#ffffff"         // Primary bar color
  secondaryBarColor="#5e5e5e" // Secondary/inactive bar color
  barWidth={2}               // Width of each frequency bar
  gap={1}                    // Gap between bars in pixels
  rounded={0}                // Border radius for rounded bars

  // === BORDER STYLING ===
  showBorder={false}         // Show border around visualization
  borderColor="#333333"      // Border color
  borderWidth={1}            // Border width in pixels
  borderRadius={0}           // Border radius for rounded corners

  // === AMPLITUDE CALCULATION ===
  amplitudeMode="peak"       // Amplitude calculation: 'peak' | 'rms' | 'adaptive'

  // === ANIMATION & RENDERING ===
  speed={3}                  // Animation speed (1-6, higher = slower)
  animateCurrentPick={true}  // Enable smooth bar transitions
  fullscreen={false}         // Fill entire parent container
  onlyActive={false}         // Show visualization only when active
  gain={1.0}                 // Audio gain multiplier (0.1-10.0, default: 1.0)

  // === STATE CONTROL ===
  isPaused={false}           // Pause visualization (freeze display)

  // === ADVANCED CUSTOMIZATION ===
  customRenderer={(context) => {
    // Custom rendering function for advanced visualizations
    // context: { canvas, audioData, width, height, ... }
  }}

  // === PLACEHOLDER CONTENT ===
  placeholder={<div>No audio source</div>} // Custom placeholder content
  showPlaceholderBackground={true}         // Show background in placeholder state

  // === CSS CLASSES ===
  className="my-waveform"    // CSS class for main container
  canvasClassName="my-canvas" // CSS class for canvas element

  // === CALLBACKS ===
  onStateChange={(state) => console.log('State:', state)} // State change callback
  onRenderStart={() => console.log('Rendering started')}  // Render start callback
  onRenderStop={() => console.log('Rendering stopped')}   // Render stop callback
  onError={(error) => console.error('Error:', error)}     // Error callback
/>

基本主张

音频来源 :

  • source - 音频来源于 useMediaAudio 或者说 useCustomAudio 钩子(视觉需要)

尺寸 :

  • width - 组件宽度,支持CSS单元和数字(默认: "100%"(中文(简体) )
  • height - 组件高度,以像素计(默认值: 200(中文(简体) )

视觉造型 :

  • backgroundColor - 背景颜色( 默认 ): "transparent"(中文(简体) )
  • barColor - 活动音频栏的主要颜色( 默认 ): "#ffffff"(中文(简体) )
  • secondaryBarColor - 非活动/后行的颜色(默认值 : "#5e5e5e"(中文(简体) )
  • barWidth - 每个频率栏以像素表示的宽度( 默认 ): 2(中文(简体) )
  • gap - 像素条之间的间隔( 默认值 : 1(中文(简体) )
  • rounded - 四舍五入条的边框半径(默认值: 0(中文(简体) )

高级道具

边框样式 :

  • showBorder - 显示可视化区域的边框( 默认 ): false(中文(简体) )
  • borderColor - 边框颜色( 默认 ): "#333333"(中文(简体) )
  • borderWidth - 以像素为单位的边框宽度( 默认值 : 1(中文(简体) )
  • borderRadius - 圆角的边框半径( 默认 ): 0(中文(简体) )

动画和渲染 :

  • speed - 动画速度从 1 - 6 起,较高数字更慢(默认 : 3(中文(简体) )
  • animateCurrentPick - 启用平滑条过渡(默认: true(中文(简体) )
  • fullscreen - 装入整个母容器(默认值 : false(中文(简体) )
  • onlyActive - 仅在音频活动时显示可视化( 默认 ): false(中文(简体) )

国家管制:

  • isPaused - 在不影响音频的情况下暂停可视化显示(默认: false(中文(简体) )

高级自定义 :

  • customRenderer - 高级可视化的自定义渲染功能
  • placeholder - 自定义反应组件,在没有音频源时显示
  • showPlaceholderBackground - 是否在占位符状态下显示背景

CSS 类 :

  • className - 主容器的CSS级
  • canvasClassName - 帆布元素的CSS类

事件召回 :

  • onStateChange - 当视觉状态发生变化时调用
  • onRenderStart - 开始渲染时打电话
  • onRenderStop - 停止渲染时打电话
  • onError - 调用 翻译错误

将媒体来源转换为可视化数据。 这是大多数使用案例的主要钩子.

const { source, error } = useMediaAudio({
  source: mediaStream  // MediaStream | HTMLAudioElement | HTMLVideoElement | AudioNode
});

重要内容: 当使用懒惰装入的音频源时(开始于 null),您必须记住选项对象以防止闪烁。 见 重要使用说明 详细情况.

支持的来源 :

  • MediaStream - 麦克风、录音软件
  • HTMLAudioElement - 音频文件
  • HTMLVideoElement - 视频文件
  • AudioNode - 网络音频 API 节点

回返情况:

  • source - AudioWave 组件的音频来源实例
  • error - 任何处理错误(无效)

使用Audio Source Hook( 语言)

说明: useAudioSource 是用于 useMediaAudio 为后向相容性维护。 新项目应使用 useMediaAudio。 。 。 .

专用钩子

为了更好的类型安全和方便,您可以使用专门的钩:

// For microphone or recording software
const { source, error } = useMediaStreamSource(mediaStream);

// For audio/video files
const { source, error } = useMediaElementSource(audioElement);

// For Web Audio API nodes
const { source, error } = useAudioNodeSource(audioNode);

// For custom audio data (Electron, Node.js, etc.)
const { source } = useCustomAudio({ provider: myProvider });

使用 CustomAudio Hook 软件

对于需要提供自定义音频数据(Electron Apps、Node.js音频处理、自定义音频管道)的高级使用案例,请使用 useCustomAudio 与自定义提供者连接 :

import { useCustomAudio } from '@audiowave/react';
import { useMemo } from 'react';

function CustomAudioApp() {
  // Create audio data provider
  const audioProvider = useMemo(() => ({
    onAudioData: (callback: (data: Uint8Array) => void) => {
      // Your audio data subscription logic
      const unsubscribe = yourAudioSource.subscribe(callback);
      return unsubscribe; // Return cleanup function
    },
    onAudioError: (callback: (error: string) => void) => {
      // Optional error handling
      const unsubscribe = yourAudioSource.onError(callback);
      return unsubscribe;
    }
  }), []);

  const { source, error } = useCustomAudio({
    provider: audioProvider,
    deviceId: 'default'
  });

  return (
    <div>
      {error && <div>Error: {error}</div>}
      <AudioWave source={source} height={120} />
    </div>
  );
}

参数:

  • provider - 音频数据实施(需要)
  • deviceId - 设备标识符(可选,默认:"默认")

回返情况:

  • source - AudioWave 组件的音频来源实例
  • status - 当前状态 : “ idle ” ; “ 活动 ” ; “ 暂停 ”
  • error - 如果有错误消息
  • isActive - 布尔表示音频是否活动
  • clearError - 清除错误状态的函数

音频数据格式 :

  • Uint8Array 数值在幅度 [0, 255]
  • 128 代表静默( 中值)
  • 128以上值表示正振幅
  • 128以下值表示负振幅
  • 阵列长度应该符合您想要的可视化分辨率

电子融合指南

用于电子应用, 使用 useCustomAudio 与本地音频处理的自定义提供者:

最佳做法:主要进程音频处理

最佳性能的主要进程中处理音频 :

主要进程main.js:

import { AudioProcessor } from '@audiowave/core';
import { ipcMain } from 'electron';

class ElectronAudioCapture {
  private audioProcessor: AudioProcessor;

  constructor() {
    this.audioProcessor = new AudioProcessor({
      bufferSize: 1024,
      skipInitialFrames: 2,
      inputBitsPerSample: 32,  // naudiodon uses 32-bit
      inputChannels: 2,        // stereo input
    });

    this.setupAudioCapture();
  }

  private setupAudioCapture() {
    // Setup your audio capture (naudiodon, etc.)
    audioCapture.on('data', (buffer: Buffer) => {
      // Process audio in main process
      const result = this.audioProcessor.process(buffer);

      if (result) {
        // Send processed data to renderer
        mainWindow.webContents.send('audio-data', result.timeDomainData);
      }
    });
  }
}

// IPC handlers
ipcMain.handle('start-audio-capture', async () => {
  // Start audio capture logic
});

ipcMain.handle('stop-audio-capture', async () => {
  // Stop audio capture logic
});

渲染器进程( R)renderer.tsx:

import { useCustomAudio } from '@audiowave/react';
import { useMemo } from 'react';

function ElectronAudioApp() {
  // Create provider for Electron IPC communication
  const electronProvider = useMemo(() => ({
    onAudioData: (callback: (data: Uint8Array) => void) => {
      const handleAudioData = (_event: any, audioData: Uint8Array) => {
        callback(audioData);
      };

      window.electronAPI.onAudioData(handleAudioData);

      return () => {
        window.electronAPI.removeAudioDataListener?.(handleAudioData);
      };
    },
    onAudioError: (callback: (error: string) => void) => {
      const handleError = (_event: any, error: string) => {
        callback(error);
      };

      window.electronAPI.onAudioError?.(handleError);

      return () => {
        window.electronAPI.removeAudioErrorListener?.(handleError);
      };
    }
  }), []);

  const { source, error } = useCustomAudio({
    provider: electronProvider,
    deviceId: 'default'
  });

  const startCapture = () => {
    window.electronAPI.startAudioCapture();
  };

  const stopCapture = () => {
    window.electronAPI.stopAudioCapture();
  };

  return (
    <div>
      {error && <div>Error: {error}</div>}
      <AudioWave source={source} height={120} />
      <button onClick={startCapture}>Start</button>
      <button onClick={stopCapture}>Stop</button>
    </div>
  );
}

预装脚本( P)preload.js:

import { contextBridge, ipcRenderer } from 'electron';

contextBridge.exposeInMainWorld('electronAPI', {
  startAudioCapture: () => ipcRenderer.invoke('start-audio-capture'),
  stopAudioCapture: () => ipcRenderer.invoke('stop-audio-capture'),
  onAudioData: (callback: (event: any, data: Uint8Array) => void) => {
    ipcRenderer.on('audio-data', callback);
  },
  onAudioError: (callback: (event: any, error: string) => void) => {
    ipcRenderer.on('audio-error', callback);
  },
  removeAudioDataListener: (callback: Function) => {
    ipcRenderer.removeListener('audio-data', callback);
  },
  removeAudioErrorListener: (callback: Function) => {
    ipcRenderer.removeListener('audio-error', callback);
  }
});

这种办法的好处:

  • 最小数据传输的优化性能
  • 维持UI响应能力
  • 多个窗口的单一处理实例

可视化控制

AudioWave为可视化显示提供了简单的控制(而不是音频本身):

使用参考文献( 模拟)

const audioWaveRef = useRef<AudioWaveController>(null);

// Basic visualization controls
audioWaveRef.current?.pause();  // Freeze display
audioWaveRef.current?.resume(); // Resume display
audioWaveRef.current?.clear();  // Clear waveform data

// State inspection methods
const isPaused = audioWaveRef.current?.isPaused(); // Check if paused
const state = audioWaveRef.current?.getState();    // Get current state: 'idle' | 'visualizing' | 'paused'
const audioData = audioWaveRef.current?.getAudioData(); // Get current audio data (Uint8Array)

音频窗口控制器方法

控制方法:

  • pause() - 暂停可视化(冻结波形显示)
  • resume() - 从暂停状态恢复可视化
  • clear() - 清除所有波形数据并重置显示

国家方法:

  • isPaused() - 返回布尔表示是否暂停可视化
  • getState() - 返回当前状态: 'idle' | 'visualizing' | 'paused'
  • getAudioData() - 返回当前音频数据为 Uint8Array

使用道具( 声明)

const [isPaused, setIsPaused] = useState(false);

<AudioWave
  source={source}
  isPaused={isPaused}  // Control via props
/>

重要内容: 这些控件只影响可视化显示,而不是你的音频源.

高度计算模式

AudioWave支持三种不同的振幅计算方法,以满足不同的可视化需要:

峰值模式( 默认)

<AudioWave source={source} amplitudeMode="peak" />
  • 最好还是:通用可视化,音乐,动态内容
  • 行为: 使用频率数据的峰值振幅值
  • 特征:高响应度,清晰显示所有音频峰值
  • 向后兼容: 默认模式, 维护已有行为

RMS 模式( 实际声音)

<AudioWave source={source} amplitudeMode="rms" />
  • 最好还是:语音分析,广播音频,感知出响比对
  • 行为: 根平方计算代表人类如何看待高音
  • 特征: 更平滑的可视化, 更好地代表所感知的音量
  • 安静的环境: 通过平稳的噪音地面过渡而增强
    • 范围 1-9: 有指数缩放的静态信号
    • 范围 10+: 有对数缩放的可听信号
    • 自然基线(1)为环境噪声下限

适应模式( 动态缩放)

<AudioWave source={source} amplitudeMode="adaptive" />
  • 最好还是: 音频级别不同,自动增益调整,内容混合
  • 行为: 根据最近的音频级别动态调整缩放
  • 特征: 自动补偿静音或高音源
  • 使用大小写: 当音频级别差异很大或无法预测时

模式切换示例

import { useState } from 'react';
import { AudioWave, useAudioSource } from '@audiowave/react';

function AmplitudeModeDemo() {
  const [mediaStream, setMediaStream] = useState<MediaStream | null>(null);
  const [amplitudeMode, setAmplitudeMode] = useState<'peak' | 'rms' | 'adaptive'>('peak');

  const { source } = useAudioSource({ source: mediaStream });

  return (
    <div>
      <AudioWave
        source={source}
        amplitudeMode={amplitudeMode}
        height={120}
        barWidth={2}
        gap={1}
      />

      <div>
        <label>Amplitude Mode:</label>
        <select
          value={amplitudeMode}
          onChange={(e) => setAmplitudeMode(e.target.value as any)}
        >
          <option value="peak">Peak (Default)</option>
          <option value="rms">RMS (Perceptual)</option>
          <option value="adaptive">Adaptive (Auto-scaling)</option>
        </select>
      </div>
    </div>
  );
}

最佳做法

处理错误

const { source, error } = useAudioSource({ source: mediaStream });

if (error) {
  return <div>Visualization error: {error.message}</div>;
}

重要使用说明

懒惰装入音频源( 适当功能需要)

当您的音频源启动时 null 后设定(常见于用户启动的情景),您 必须 记住 useAudioSource 选项。 没有这个,可视化将不断闪烁并重启,使其无法使用:

- 这会导致闪烁:

function MyAudioApp() {
  const [mediaStream, setMediaStream] = useState<MediaStream | null>(null);

  // This creates a new options object on every render!
  const { source } = useMediaAudio({
    source: mediaStream,
    onError: (error) => console.error('Audio error:', error)
  });

  // ... rest of component
}

QQ CORRECT - 纪念选项对象 :

function MyAudioApp() {
  const [mediaStream, setMediaStream] = useState<MediaStream | null>(null);

  // Step 1: Memoize the onError callback
  const handleAudioError = useCallback((error: Error) => {
    console.error('Audio error:', error);
  }, []);

  // Step 2: Memoize the entire options object
  const audioSourceOptions = useMemo(() => ({
    source: mediaStream,
    onError: handleAudioError,
  }), [mediaStream, handleAudioError]);

  // Step 3: Use the memoized options
  const { source } = useMediaAudio(audioSourceOptions);

  const startRecording = async () => {
    const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
    setMediaStream(stream); // This triggers re-render with new source
  };

  return (
    <div>
      <button onClick={startRecording}>Start Recording</button>
      <AudioWave source={source} />
    </div>
  );
}

为什么需要这样做?

  • 每个参数都会创建一个新选项对象 { source: mediaStream, onError: ... }
  • useMediaAudio 视此为"变化"并重新初始化音频处理
  • 这导致可视化反复闪烁并重启,使其无法使用
  • 这不是性能问题 这是正常运行的功能要求

快速引用 - 复制此模式 :

// Always use this pattern for lazy-loaded audio sources
const handleError = useCallback((error: Error) => {
  console.error('Audio error:', error);
}, []);

const options = useMemo(() => ({
  source: yourAudioSource, // MediaStream | HTMLAudioElement | etc.
  onError: handleError,
}), [yourAudioSource, handleError]);

const { source } = useMediaAudio(options);

性能优化

纪念组件道具

// Memoize AudioWave props for better performance
const audioWaveProps = useMemo(() => ({
  source,
  height: 200,
  barWidth: 2,
  gap: 1,
  backgroundColor: 'transparent',
  barColor: '#ffffff'
}), [source]);

return <AudioWave {...audioWaveProps} />;

响应设计

<AudioWave
  source={source}
  width="100%"
  height={window.innerWidth < 768 ? 80 : 120}
  style={{ maxWidth: '100%' }}
/>

类型脚本支持

包含完整类型的全部类型脚本支持 :

import type {
  AudioWaveProps,
  AudioWaveController,
  AudioSource,
  UseAudioSourceOptions
} from '@audiowave/react';

浏览器支持

  • Chrome 66+ (2018年3月) (英语)
  • Firefox 60+ (2018年5月) (英语)
  • Safari 14+ (2020年9月) (英语)
  • 79岁以上(2020年1月)

需要Web音频API和MediaStream API支持.

许可证

麻省理工学院 温度

版本与发布记录

@audiowave/react 共发布 8 个版本,首次发布于 2025/07/26;过去 12 个月发布了 0 个版本。

版本发布日期距今
0.6.2latest2025/10/311 年前
0.6.12025/08/101.2 年前
0.6.02025/08/021.3 年前
0.5.02025/08/011.3 年前
0.4.02025/08/011.3 年前
0.3.02025/07/311.3 年前

关于 @audiowave/react 的常见问题

@audiowave/react 是什么?

反射音频可视化组件

如何安装 @audiowave/react?

在项目目录运行 npm install @audiowave/react,或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖:react(>=16.8.0)、react-dom(>=16.8.0)。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖,Yarn 需要手动安装。

@audiowave/react 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@audiowave/react 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@audiowave/react 可以商用吗?

@audiowave/react 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@audiowave/react 的下载量有多少?

根据 npm 官方下载统计,@audiowave/react 在 2026/10/07 – 2026/11/05 这 30 天内被下载 784,096 次,日均约 26,137 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@audiowave/react 还在维护吗?

最新版本 0.6.2 发布于 2025/10/31(1 年前);至今共发布 8 个版本,其中过去 12 个月发布了 0 个;首次发布于 2025/07/26。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。