更新记录

1.1.0(2026-10-18)

兼容蒸汽模式


平台兼容性

uni-app(5.26)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
× √ × × √ × √ √ ×
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × × × × × × × × × × ×

uni-app x(5.26)

Chrome Safari Android iOS 鸿蒙 微信小程序
× × √ √ × ×

其他

多语言 暗黑模式 宽屏模式 蒸汽模式
× × × √

UTS 分片录音 X

前台开始 → 退后台或锁屏继续录音 → 分片保存 → 停止后拿到完整音频。

适合语音采集、访谈记录、录音上传与转写前的音频采集环节。原生录制 AAC / M4A,无第三方录音 SDK;界面、上传和业务处理由你的项目决定。

能力 用法
录音控制 开始、暂停、继续、停止
后台录音 Android 麦克风前台服务;iOS 后台音频模式
通知控制 Android 通知栏暂停、继续、停止,标题和说明可自定义
自动分片 按毫秒设置分片时长,每段完成后回调本地路径
完整音频 停止后返回合并结果,原始分片继续保留
状态与音量 查询录音时长、状态、片段数量,监听分贝变化
历史记录 会话索引落盘,重开 App 后查看已保存的录音与片段
中断保护 异常结束后找回已完成片段,标记为“已中断”
文件管理 查询会话与片段,删除会话文件
演示页 附带权限申请、录音控制、片段试听与复制路径

兼容性

项目类型 Android iOS 演示文件
uni-app x · Vapor 蒸汽模式 支持,Android 7.0+ 支持 index.uvue
uni-app x · VDOM 模式 支持,Android 7.0+ 支持 index.uvue
uni-app · Vue3 支持,Android 7.0+ 支持 index.vue
Web、小程序、鸿蒙、nvue 不支持 不支持 —

使用 HBuilderX 5.26 或以上版本。两种 uni-app x 渲染模式共用 UTS API 和演示页,无需改插件调用。

录音必须由用户在前台页面主动开始。开始后可以离开页面、切到桌面或锁屏。Android 使用带通知的麦克风前台服务和录音期间的 CPU 唤醒锁;iOS 使用系统后台音频能力。

强制停止、系统终止进程、关机后不能继续录音。重新打开 App 会恢复历史索引与可用片段,不会自动开启麦克风。Android 厂商省电策略仍可能终止服务;iOS 来电、麦克风被占用等情况由系统决定中断和恢复。

第 1 步:导入插件

把整个 austin-recorder-x 文件夹放到项目的 uni_modules 中,保留 utssdk 目录。

你的项目/
  uni_modules/
    austin-recorder-x/
      package.json
      index.uvue       ← uni-app x 演示页
      index.vue        ← uni-app Vue3 演示页
      utssdk/          ← 必须保留

插件 ID 为 austin-recorder-x。从旧的 austin-recorder 迁移时,将业务代码的导入路径改为新 ID;不要在同一应用里同时启动两个录音引擎。

第 2 步:配置麦克风与后台音频

Android

插件自带 utssdk/app-android/AndroidManifest.xml,自动合并以下配置,无需在业务页面重复声明:

配置 用途
RECORD_AUDIO 用户授权后访问麦克风
FOREGROUND_SERVICE、FOREGROUND_SERVICE_MICROPHONE 运行麦克风前台服务
WAKE_LOCK 录音时维持 CPU 工作,暂停或停止后释放
POST_NOTIFICATIONS Android 13+ 展示通知栏录音控制
RecorderForegroundService 注册 microphone 类型的非导出服务

首次导入或从旧版升级后,必须重新制作并安装自定义基座。仅热更新页面无法添加原生服务。开始前调用 requestRecorderPermission:先申请麦克风,Android 13+ 再询问通知权限。拒绝通知不影响麦克风授权,但通知栏控制可能不可见,此时回到页面操作。

默认使用应用私有目录,不需要相册或外部存储权限。前台服务的“前台”指系统服务等级,不要求用户一直停留在录音页面。

iOS · uni-app x

打开项目根目录的 manifest.json,合并下面的配置。麦克风文案改成你的真实业务用途:

{
  "app-ios": {
    "distribute": {
      "UIBackgroundModes": "audio",
      "privacyDescription": {
        "NSMicrophoneUsageDescription": "用于录制用户主动发起的语音记录"
      }
    }
  }
}

也可以在 HBuilderX 的 manifest.json 可视化页面进入「iOS App配置」:后台运行能力填写 audio,隐私许可描述填写麦克风用途。已有其他后台模式时保留它们,以逗号分隔。

iOS · 普通 uni-app

普通 uni-app 的配置位置不同,放在 app-plus.distribute.ios:

{
  "app-plus": {
    "distribute": {
      "ios": {
        "UIBackgroundModes": "audio",
        "privacyDescription": {
          "NSMicrophoneUsageDescription": "用于录制用户主动发起的语音记录"
        }
      }
    }
  }
}

这两项必须配置在宿主项目中:NSMicrophoneUsageDescription 用于申请麦克风,UIBackgroundModes: audio 用于后台录音。插件中虽附带默认 Info.plist,接入时仍请按上面的对应路径填写宿主 manifest.json。

配置后重新云打包并安装新基座;仅同步页面或原生插件、重新签名已有基座,不能补齐旧安装包的用途说明和后台声明。配置位置参考 uni-app x iOS 配置 与 uni-app 后台运行配置。

第 3 步:制作并选择自定义基座

  1. 在 HBuilderX 选择当前项目,进入「运行 → 运行到手机或模拟器 → 制作自定义调试基座」。
  2. 选择 Android 或 iOS;iOS 真机使用与你的应用标识匹配的证书和描述文件。录音本身不需要 APNs 推送证书或 .p8。
  3. 打包完成后,在运行配置中选择「自定义基座」,安装到设备再运行项目。
  4. 后续修改原生插件或权限配置时重新制作基座;仅修改演示页样式或业务调用时正常运行即可。

第 4 步:先打开演示页

在 pages.json 的 pages 数组中加入:

{
  "path": "uni_modules/austin-recorder-x/index",
  "style": {
    "navigationBarTitleText": "分片录音 X",
    "disableScroll": true
  }
}

从你的页面进入:

uni.navigateTo({ url: '/uni_modules/austin-recorder-x/index' })

测试顺序:选择 10秒 → 开始录音并授权 → 返回桌面、锁屏至少 30 秒 → 回页面确认片段增加 → 暂停、继续 → 停止并保存 → 试听片段和完整音频。Android 也可以从通知栏控制;停止后重新打开 App 检查历史录音。

要使用自己的页面,把插件内的 index.uvue(uni-app x)或 index.vue(uni-app Vue3)复制到 pages/recorder/index.uvue / .vue,并注册 pages/recorder/index。页面中的 API 与类型均使用 @/uni_modules/austin-recorder-x 下的绝对路径导入,无需改动导入路径。

演示页切后台、返回上一页均保留录音,重新进入会读取当前状态。结束录音请点击“停止并保存”或 Android 通知中的“停止”。业务中的持续状态管理、上传等回调建议放在应用级模块,页面通过查询 API 刷新;后台页面回调执行时机不能代替原生录音状态。

第 5 步:接入自己的按钮

uni-app x 页面在 <script setup lang="uts"> 中使用以下代码:

import {
  requestRecorderPermission, startRecorder, stopRecorder,
  pauseRecorderSync, resumeRecorderSync
} from '@/uni_modules/austin-recorder-x'
import {
  StartRecorderOptions, StopRecorderOptions,
  RequestRecorderPermissionOptions
} from '@/uni_modules/austin-recorder-x'

function start() {
  const permission: RequestRecorderPermissionOptions = {
    success: (res) => {
      if (!res.granted) return
      const options: StartRecorderOptions = {
        segmentDurationMs: 10000,
        maxDurationMs: 3600000,
        enableMetering: true,
        notificationTitle: '语音记录',
        notificationText: '录音进行中,点击返回应用',
        onStateChange: (event) => { console.log('状态', event.status) },
        onSegmentReady: (segment) => { console.log('片段路径', segment.filePath) },
        fail: (error) => { console.log(error.errCode, error.errMsg, error.note) }
      }
      startRecorder(options)
    },
    fail: (error) => { console.log('权限失败', error.errMsg) }
  }
  requestRecorderPermission(permission)
}

function pause() { console.log(pauseRecorderSync()) }
function resume() { console.log(resumeRecorderSync()) }
function stop() {
  const options: StopRecorderOptions = {
    reason: 'manual-stop',
    success: (session) => {
      // 以这个回调中的路径为准,iOS 多片段合并为异步操作。
      console.log('完整音频', session.mergedFilePath)
      console.log('合并说明', session.mergeNote)
    },
    fail: (error) => { console.log(error.errCode, error.errMsg, error.note) }
  }
  stopRecorder(options)
}

普通 Vue3 的 <script setup> 用法相同,删除类型导入及变量上的 : XxxOptions 标注即可。完整示例见 index.vue。

播放已保存的录音

等待停止并保存成功后,传入 session.mergedFilePath 或 segment.filePath。iOS 给 uni.createInnerAudioContext() 传递本插件返回的绝对路径时,加上 file:// 前缀;不要额外调用 encodeURI。演示页已处理。

import { getRecorderStatusSync } from '@/uni_modules/austin-recorder-x'

const previewAudio = uni.createInnerAudioContext()
previewAudio.onError((error) => { console.log(error.errCode, error.errMsg) })

function playRecording(path: string) {
  if (path.length == 0) return
  previewAudio.stop()
  const isIOS = getRecorderStatusSync().platform == 'ios'
  previewAudio.src = isIOS && path.startsWith('/') ? 'file://' + path : path
  previewAudio.play()
}

onUnload(() => { previewAudio.destroy() })

普通 Vue3 页面删除参数上的 : string。file:// 仅在播放时添加,插件返回的路径仍用于文件管理和业务处理。

API 一览

API 参数 返回 / 结果
requestRecorderPermission(options) 权限回调 success(RecorderPermissionResult) 或 fail(RecorderFail)
startRecorder(options) StartRecorderOptions success(RecorderSessionInfo) 表示已开始,不是录音结束
pauseRecorderSync() 无 RecorderOperationResult
resumeRecorderSync() 无 RecorderOperationResult
stopRecorder(options) reason?、结果回调 success(RecorderSessionInfo) 返回录音及合并结果
getRecorderStatusSync() 无 RecorderStatus
getCurrentSessionSync() 无 RecorderSessionInfo \| null
getRecorderHistorySync() 无 历史快照:sessions 会话数组、segments 已完成片段数组
listRecorderSessionsSync() 无 保留的原生会话数组接口;iOS 页面请用历史快照
listRecorderSegmentsSync(sessionId) 会话 ID 保留的原生片段数组接口;iOS 页面请用历史快照
deleteRecorderSessionSync(sessionId) 会话 ID 删除该会话及文件;录音/暂停中及 iOS 合并中的会话不可删除
openRecorderPermissionSettingsSync() 无 打开应用权限设置,返回操作结果

普通 uni-app Vue3 中,使用 if (session && session.sessionId) 判断是否取到了当前会话;部分运行基座在无会话时会返回空字符串,不能只判断 session != null。

开始录音 StartRecorderOptions

字段 类型 / 默认值 说明
scene string / trip-record 可选业务标识,不需要选择预设场景
sessionId string / 自动生成 建议不传;自行传入时使用唯一的字母、数字、下划线或连字符组合,最长 96 字符,不能复用已有会话
outputDir string / 应用私有录音目录 建议不传。Android 视为根目录并追加 sessionId;iOS 绝对路径作为本会话目录,相对路径拼到私有录音目录下,必须是不存在或空的目录。不要复用其他会话或业务目录
segmentDurationMs number / 300000 每段时长,毫秒;填写 0 关闭自动分片,否则至少 1000,调试建议 10000
maxDurationMs number / 3600000 最大有效录音时长,毫秒;0 表示不限,否则至少 1000;暂停时间不计入
enableMetering boolean / true 是否开启音量回调
notificationTitle string / 正在录音 Android 前台服务通知标题;iOS 忽略
notificationText string / 录音服务运行中,点击返回应用 Android 通知说明;iOS 忽略
onStateChange (RecorderStateEvent) => void 状态与周期进度通知,同一 status 可能多次回调
onMetering (RecorderMeteringEvent) => void 音量及录音时长通知
onSegmentReady (RecorderSegmentInfo) => void 一段录音完成并落盘时触发
success、fail、complete 回调,可选 分别对应开始成功、开始失败、本次开始操作结束;complete 不是整段录音结束

权限与操作结果

类型 字段 说明
RecorderOperationResult ok、platform、action、errCode、errMsg、note 成功状态、平台、动作、错误码、错误内容及补充说明
RecorderPermissionResult 上述字段 + granted、canAskAgain、permissions、deniedPermissions 是否已授权、能否再次询问及权限列表。拒绝后可引导打开设置,实际是否弹窗由系统决定
RecorderFail errSubject、errCode、errMsg、platform、action、note 失败详情,错误主题为 austin-recorder-x

状态与事件

类型 字段 说明
RecorderStatus supported、platform 当前运行环境与支持状态
status、sessionId、scene 状态、会话 ID、业务标识
durationMs、segmentCount、meterDb、note 有效录音时长、已生成片段数、音量与说明
RecorderStateEvent sessionId、scene、status、durationMs、segmentCount、reason、time 状态变化;time 为毫秒时间戳
RecorderMeteringEvent sessionId、durationMs、db、peak、time 音量与时间;数值用于音量反馈,不作为校准分贝仪读数

status 常见值:idle 待命、recording 录音中、paused 已暂停、stopped 已停止、error 异常、interrupted 上次会话意外结束。Android 创建期间还可能出现 starting。

文件与会话

类型 字段 说明
RecorderSegmentInfo sessionId、index、filePath 会话 ID、片段序号、已完成片段的绝对路径
durationMs、sizeBytes、createdAt 片段时长(毫秒)、大小(字节)、生成时间(毫秒时间戳)
RecorderSessionInfo sessionId、scene、status、platform 会话身份、业务标识、状态、平台
outputDir、startedAt、endedAt 输出目录、起止时间戳
totalDurationMs、segmentCount 有效录音时长与片段数
mergedFilePath、mergedSizeBytes、mergeNote 完整音频路径、字节数与合并说明;无可用结果时路径为空

多个片段停止后生成 merged.m4a;iOS 只有一个片段时直接返回该片段作为完整音频。不要把“收到停止状态”当作“合并已经完成”,应等待 stopRecorder.success,并检查路径与 mergeNote。合并失败时原始片段仍可取出处理。

会话索引与已完成片段会保存到本机,重开 App 后统一通过 getRecorderHistorySync() 查询:

import { getRecorderHistorySync } from '@/uni_modules/austin-recorder-x'

const history = getRecorderHistorySync()
console.log('全部会话', history['sessions'])
console.log('全部已完成片段', history['segments'])

快照内两组数组的字段分别对应上表的 RecorderSessionInfo 和 RecorderSegmentInfo;用 sessionId 关联会话和片段。附带演示页已处理列表显示与筛选,可直接复制。iOS 的 Vapor / 普通 uni-app 页面使用这个接口,避免部分基座直接返回自定义对象数组时丢失字段。

上次仍在录音或暂停的会话会标记为 interrupted;可用片段可以试听或交给业务处理,不会自动续录。强制结束时正在写入的尾段可能损坏,不能保证恢复:Android 会将识别出的无效尾段保留为 .incomplete,iOS 保留未完成文件但不将其列为有效片段。

自动分片使用停止当前录制、开始下一段的方式,切换有短暂间隙,不适合要求采样连续、无缝录音的场景。卸载 App 或清除应用数据会删除私有音频与索引;重要记录应由业务上传或导出。

常见问题

导入了但 API 不可用?

确认模块目录完整、导入 ID 正确,并重新制作和选中包含本插件的自定义基座。不要只把 JS 页面同步到旧基座。

Android 提示 Please register permissions ... RECORD_AUDIO?

这表示当前安装的基座未声明麦克风权限。确认插件的 utssdk/app-android/AndroidManifest.xml 随插件一起导入,再制作、安装并选择最新自定义基座。手机设置里的“允许麦克风”只负责用户授权,不能补充安装包缺失的权限声明。若错误内容已经改变,请按新的 errMsg 排查。

iOS 点击“申请权限”或“开始录音”闪退?

查看崩溃日志:若出现 TCC 和 NSMicrophoneUsageDescription,说明当前安装包缺少麦克风用途说明。按第 2 步填写宿主 manifest.json,再按第 3 步重新制作、安装并选中新基座。录音插件会在两个入口检查该说明,缺失或为空时通过 fail / complete 返回 9101002,具体处理方法见 note;更新了页面但基座仍是旧版本时,检查不会自动生效。

录音停止了却没有完整音频?

先等待 stopRecorder.success,读取 mergeNote。过短录音、麦克风中断或合并失败可能无法得到完整文件;可以读取 getRecorderHistorySync() 的 segments,按 sessionId 检查已经落盘的片段。

如何测试后台?

按第 4 步在真机录制,锁屏期间跨过多个分片周期,回到应用后核对文件数量、实际时长并试听。Android 确认通知里的暂停、继续、停止生效;若厂商省电策略中断服务,在系统电池设置中允许该 App 后台运行。iOS 确认安装包包含 audio 后台模式,再检查锁屏和来电中断后的表现。模拟器用于调用和文件流程调试,后台表现以真机为准。

需要服务器、Key、推送证书吗?

录音、分片和合并都在本机执行,不需要服务器或 Key。上传、云端转写等能力由业务另行接入。

失败怎么定位?

打印 errCode、errMsg 与 note:9101002 权限未授予或 iOS 麦克风用途说明缺失;9101003 初始化失败;9101004 已有录音;9101005/9101006/9101007 当前状态不能暂停/继续/停止;9101008 原生运行环境不可用;9101009/9101010 文件创建或写入失败;9101011 删除失败;9101001/9101012 平台或操作不支持。

版本

1.1.0:新增 Android 前台录音服务、通知控制、录音期间唤醒锁;新增 iOS 原生分片计时和音频中断处理;支持历史索引持久化、统一历史快照查询、异常结束后的片段恢复,以及跨页面录音。

1.0.0:独立插件 ID austin-recorder-x,提供 uni-app x 的 Vapor / VDOM 演示及普通 uni-app Vue3 演示,保留分片录音、暂停继续、合并与会话管理 API。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

Android 需要 RECORD_AUDIO、FOREGROUND_SERVICE、FOREGROUND_SERVICE_MICROPHONE、WAKE_LOCK,Android 13+ 通知栏控制使用 POST_NOTIFICATIONS;iOS 需要 NSMicrophoneUsageDescription 和 UIBackgroundModes audio。用户前台开始录音后可后台运行,强制停止后不能继续录音。

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

经用户授权在本机采集音频并默认保存到应用私有目录,不向服务器上传音频或个人信息。播放与复制路径由用户主动触发。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

无

暂无用户评论。