Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
145 changes: 143 additions & 2 deletions packages/website-astro/public/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3730,7 +3730,7 @@ function Demo() {

---

# Browser hooks (49)
# Browser hooks (50)

## useBroadcastChannel

Expand Down Expand Up @@ -5767,6 +5767,147 @@ function Demo() {

---

## useMicrophone

URL: https://reactuse.com/browser/usemicrophone/
Category: browser
Description: useMicrophone is a React hook for the microphone — open a stream, read a real-time audio level, and record audio to a Blob with MediaRecorder.
Import: `import { useMicrophone } from '@reactuses/core'`

# useMicrophone

React hook for capturing microphone audio

`useMicrophone` wraps [`getUserMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia), the [Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API), and [`MediaRecorder`](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) into a single hook. It opens and closes the microphone stream, exposes a throttled audio `level` (0–1, RMS) suitable for a VU meter, and records the active stream to a `Blob` with a hook-managed object URL.

The live-stream controls (`start` / `stop`) and the recording controls (`startRecording` / `stopRecording` / `pauseRecording` / `resumeRecording`) are independent: you can show a level meter without recording, and start or stop a recording without dropping the microphone.

### When to Use

- Building voice-note or dictation UIs where the user sees a live input level before and while recording
- Adding "speak now" prompts or microphone calibration screens that need a VU meter but no capture
- Recording short audio clips to a `Blob` for upload or local playback

### Notes

- **SSR-safe**: Returns `isSupported: false` and no-op controls during server-side rendering. No `navigator.mediaDevices` access occurs on the server.
- **`start()` before `startRecording()`**: Recording captures an already-open stream. Call `start()` first; calling `startRecording()` without an active stream sets `error` instead of recording.
- **HTTPS required**: In production the microphone requires a secure context (HTTPS). The browser prompts for permission on the first `start()`.
- **Object URL lifecycle**: `audioUrl` is created and revoked by the hook — it is replaced on the next recording and revoked on unmount, so consumers do not need to call `URL.revokeObjectURL` themselves.
- **Mime type**: The recording format is auto-selected from the formats the browser supports (`audio/webm;codecs=opus`, `audio/webm`, `audio/mp4`, `audio/ogg;codecs=opus`). The resolved value is exposed as `mimeType`.
- **Related hooks**: Use `useMediaDevices` to enumerate microphones and pass a `deviceId`, or `useSpeechRecognition` for speech-to-text.

## Usage

```tsx live
function Demo() {
const {
isSupported,
isActive,
level,
isRecording,
isPaused,
audioUrl,
mimeType,
error,
start,
stop,
startRecording,
stopRecording,
pauseRecording,
resumeRecording,
} = useMicrophone();

if (!isSupported) {
return <div>Microphone is not supported in this browser</div>;
}

const levelPercent = Math.round(level * 100);

return (
<div>
<div style={{ marginBottom: '16px' }}>
<p>
<strong>Microphone:</strong> {isActive ? 'Open' : 'Closed'}
{' · '}
<strong>Recording:</strong>{' '}
{isRecording ? (isPaused ? 'Paused' : 'Recording...') : 'Idle'}
</p>

<div
style={{
height: '16px',
width: '100%',
borderRadius: '4px',
backgroundColor: 'var(--ifm-color-emphasis-200)',
overflow: 'hidden',
}}
>
<div
style={{
height: '100%',
width: `${levelPercent}%`,
backgroundColor:
levelPercent > 70
? 'var(--ifm-color-danger)'
: 'var(--ifm-color-success)',
transition: 'width 80ms linear',
}}
/>
</div>
<p style={{ fontSize: '13px', color: 'var(--ifm-color-content-secondary)' }}>
Input level: {levelPercent}%
</p>
</div>

<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', marginBottom: '12px' }}>
<button onClick={() => start()} disabled={isActive}>
Open mic
</button>
<button onClick={() => stop()} disabled={!isActive}>
Close mic
</button>
<button onClick={() => startRecording()} disabled={!isActive || isRecording}>
Record
</button>
<button onClick={() => stopRecording()} disabled={!isRecording}>
Stop recording
</button>
<button onClick={() => pauseRecording()} disabled={!isRecording || isPaused}>
Pause
</button>
<button onClick={() => resumeRecording()} disabled={!isPaused}>
Resume
</button>
</div>

{audioUrl && (
<div style={{ marginBottom: '12px' }}>
<p style={{ fontSize: '13px', color: 'var(--ifm-color-content-secondary)' }}>
Recorded clip ({mimeType || 'default format'}):
</p>
<audio src={audioUrl} controls />
</div>
)}

{error && (
<p style={{ color: 'var(--ifm-color-danger)' }}>
<strong>Error:</strong> {error.message}
</p>
)}
</div>
);
}
```

## Common Use Cases

- **Voice notes**: Open the mic so the user sees a live level, then record to a `Blob` and play it back or upload it.
- **Level metering**: Drive a VU meter or waveform from `level` without recording anything.
- **Microphone calibration**: Let users confirm the right device is picked up before they start.

---

## useMobileLandscape

URL: https://reactuse.com/browser/usemobilelandscape/
Expand Down Expand Up @@ -7685,4 +7826,4 @@ function Demo() {
---


Generated: 2026-05-14T09:08:21.446Z | Total hooks: 113
Generated: 2026-05-20T20:21:53.456Z | Total hooks: 114
13 changes: 11 additions & 2 deletions packages/website-astro/public/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -619,7 +619,7 @@ React Element Hooks that tracks window size
Documentation: https://reactuse.com/element/usewindowsize/
Import: `import { useWindowSize } from '@reactuses/core'`

### Browser (49 hooks)
### Browser (50 hooks)

#### useBroadcastChannel

Expand Down Expand Up @@ -828,6 +828,15 @@ Ease with media query
Documentation: https://reactuse.com/browser/usemediaquery/
Import: `import { useMediaQuery } from '@reactuses/core'`

#### useMicrophone

useMicrophone is a React hook for the microphone — open a stream, read a real-time audio level, and record audio to a Blob with MediaRecorder.

React hook for capturing microphone audio

Documentation: https://reactuse.com/browser/usemicrophone/
Import: `import { useMicrophone } from '@reactuses/core'`

#### useMobileLandscape

useMobileLandscape is a React hook that returns true when the device is a mobile in landscape orientation, updating reactively on rotation.
Expand Down Expand Up @@ -1101,4 +1110,4 @@ PDD (Pinduoduo), Shopee, Ctrip, Bambu Lab
Unlicense - Use freely without restrictions

---
Generated: 2026-05-14T09:08:21.396Z | Total Hooks: 113
Generated: 2026-05-20T20:21:53.426Z | Total Hooks: 114
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
title: useMicrophone 用法与示例
sidebar_label: useMicrophone
description: "useMicrophone 是一个用于麦克风的 React hook,可打开音频流、读取实时音量电平,并通过 MediaRecorder 将音频录制为 Blob。"
---
# useMicrophone

用于采集麦克风音频的 React hook

`useMicrophone` 将 [`getUserMedia`](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia)、[Web Audio API](https://developer.mozilla.org/en-US/docs/Web/API/Web_Audio_API) 和 [`MediaRecorder`](https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder) 封装进同一个 hook。它负责打开和关闭麦克风音频流,暴露一个经过节流的音量 `level`(0–1,RMS),适合用于音量条,并可将当前音频流录制为 `Blob`,同时由 hook 管理对象 URL 的生命周期。

实时音频流控制(`start` / `stop`)与录音控制(`startRecording` / `stopRecording` / `pauseRecording` / `resumeRecording`)相互独立:你可以只显示音量条而不录音,也可以在不关闭麦克风的情况下开始或停止录音。

### 使用场景

- 构建语音备忘录或听写界面,让用户在录音前和录音中都能看到实时输入电平
- 添加「请说话」提示或麦克风校准界面 —— 需要音量条但不需要录音
- 将短音频片段录制为 `Blob` 用于上传或本地播放

### 注意事项

- **SSR 安全**:在服务端渲染期间返回 `isSupported: false` 和空操作的控制函数。服务端不会访问 `navigator.mediaDevices`。
- **先 `start()` 再 `startRecording()`**:录音采集的是已打开的音频流。请先调用 `start()`;在没有活动流时调用 `startRecording()` 会设置 `error` 而不会开始录音。
- **需要 HTTPS**:在生产环境中,麦克风需要安全上下文(HTTPS)。浏览器会在首次 `start()` 时请求权限。
- **对象 URL 生命周期**:`audioUrl` 由 hook 创建和释放 —— 它会在下一次录音时被替换,并在卸载时被释放,因此使用方无需自行调用 `URL.revokeObjectURL`。
- **Mime 类型**:录音格式会从浏览器支持的格式中自动选择(`audio/webm;codecs=opus`、`audio/webm`、`audio/mp4`、`audio/ogg;codecs=opus`)。最终解析出的值通过 `mimeType` 暴露。
- **相关 hooks**:使用 `useMediaDevices` 枚举麦克风并传入 `deviceId`,或使用 `useSpeechRecognition` 进行语音转文字。

## 基本用法

```tsx live
function Demo() {
const {
isSupported,
isActive,
level,
isRecording,
isPaused,
audioUrl,
mimeType,
error,
start,
stop,
startRecording,
stopRecording,
pauseRecording,
resumeRecording,
} = useMicrophone();

if (!isSupported) {
return <div>此浏览器不支持麦克风</div>;
}

const levelPercent = Math.round(level * 100);

return (
<div>
<div style={{ marginBottom: '16px' }}>
<p>
<strong>麦克风:</strong> {isActive ? '已打开' : '已关闭'}
{' · '}
<strong>录音:</strong>{' '}
{isRecording ? (isPaused ? '已暂停' : '录音中...') : '空闲'}
</p>

<div
style={{
height: '16px',
width: '100%',
borderRadius: '4px',
backgroundColor: 'var(--ifm-color-emphasis-200)',
overflow: 'hidden',
}}
>
<div
style={{
height: '100%',
width: `${levelPercent}%`,
backgroundColor:
levelPercent > 70
? 'var(--ifm-color-danger)'
: 'var(--ifm-color-success)',
transition: 'width 80ms linear',
}}
/>
</div>
<p style={{ fontSize: '13px', color: 'var(--ifm-color-content-secondary)' }}>
输入电平: {levelPercent}%
</p>
</div>

<div style={{ display: 'flex', gap: '8px', flexWrap: 'wrap', marginBottom: '12px' }}>
<button onClick={() => start()} disabled={isActive}>
打开麦克风
</button>
<button onClick={() => stop()} disabled={!isActive}>
关闭麦克风
</button>
<button onClick={() => startRecording()} disabled={!isActive || isRecording}>
录音
</button>
<button onClick={() => stopRecording()} disabled={!isRecording}>
停止录音
</button>
<button onClick={() => pauseRecording()} disabled={!isRecording || isPaused}>
暂停
</button>
<button onClick={() => resumeRecording()} disabled={!isPaused}>
继续
</button>
</div>

{audioUrl && (
<div style={{ marginBottom: '12px' }}>
<p style={{ fontSize: '13px', color: 'var(--ifm-color-content-secondary)' }}>
录制的片段({mimeType || '默认格式'}):
</p>
<audio src={audioUrl} controls />
</div>
)}

{error && (
<p style={{ color: 'var(--ifm-color-danger)' }}>
<strong>错误:</strong> {error.message}
</p>
)}
</div>
);
}
```

## 常见用例

- **语音备忘录**:打开麦克风让用户看到实时电平,然后录制为 `Blob` 并回放或上传。
- **音量监测**:用 `level` 驱动音量条或波形,而无需录制任何内容。
- **麦克风校准**:让用户在开始前确认采集到的是正确的设备。

%%API%%
Loading
Loading