Git Product home page Git Product logo

benz-amr-recorder's Introduction

AMR 录音机 GitHub stars

(README in English)

npm npm size gzip size

纯前端解码、播放、录音、编码 AMR 音频,无须服务器支持,基于 amr.jsRecorderJs

注意:由于使用了 amr.js 做编码和解码,因此 js 文件(压缩后,未 gzip)接近 500 KB,使用前请考虑。

2019-10-05 更新 (v1.1.0):

增加浏览器支持检测功能,增加暂停播放、设置播放进度功能。

2022-09-26 更新 (v1.1.4):

  1. 使用 create-react-app 脚手架测试了在 React 的使用情况,结论:没有发现问题。代码点我
  2. 增加一个好像没有什么用的 destroy(),功能:释放amr数据和pcm数据、解绑所有事件、令对象作废。
  3. 新功能:解绑事件,用法:给事件传入 null,例如:amr.onPlay(null)

2022-09-27 更新 (v1.1.5):

更新 rollup 库以消除 github 的安全提醒。

特性

  • 方便的 API 实现解码、播放、录音、编码 AMR 文件。
  • 支持 url 和 blob (即<input type="file">)方式获取 AMR。
  • 支持将浏览器 <audio> 所支持的音频格式(例如 MP3 或 OGG 音频)转换成 AMR 音频。
  • 编码后的 AMR 文件可下载,无须服务器。

Demo

demo.html

浏览器兼容性

最新的浏览器兼容性请参阅 Can I Use

安装

方法一:引入 js 文件

<script type="text/javascript" src="./BenzAMRRecorder.min.js"></script>

方法二:使用 npm

NPM

npm install benz-amr-recorder
var BenzAMRRecorder = require('benz-amr-recorder');

用法

注意: 建议把 initWithXXX()play() 方法绑定到一个用户事件中(例如 clicktouchstart)。因为几乎所有移动设备(以及桌面版 Chrome 70+)都禁止页面自动播放音频。参考:

播放 AMR:

var amr = new BenzAMRRecorder();
amr.initWithUrl('path/to/voice.amr').then(function() {
  amr.play();
});
amr.onEnded(function() {
  alert('播放完毕');
})

播放本地文件:

<input type="file" id="amr-file" accept=".amr">
var amr = new BenzAMRRecorder();
var amrFileObj = document.getElementById('amr-file');
amrFileObj.onchange = function() {
  amr.initWithBlob(this.files[0]).then(function() {
    amr.play();
  });
}

录制 AMR:

var amrRec = new BenzAMRRecorder();
amrRec.initWithRecord().then(function() {
  amrRec.startRecord();
});

下载 AMR:

window.location.href = window.URL.createObjectURL(amr.getBlob());

把 MP3 转换成 AMR (需要浏览器原生支持 MP3):

var amrFromMp3 = new BenzAMRRecorder();
amrFromMp3.initWithUrl('path/to/file.mp3').then(function() {
  // 下载 amr 文件
  window.location.href = window.URL.createObjectURL(amrFromMp3.getBlob());
})

API

初始化对象

/**
 * 是否已经初始化
 * @return {boolean}
 */
amr.isInit();
/**
 * 使用浮点数据初始化
 * @param {Float32Array} array
 * @return {Promise}
 */
amr.initWithArrayBuffer(array);
/**
 * 使用 Blob 对象初始化( <input type="file">)
 * @param {Blob} blob
 * @return {Promise}
 */
amr.initWithBlob(blob);
/**
 * 使用 url 初始化
 * @param {string} url
 * @return {Promise}
 */
amr.initWithUrl(url);
/**
 * 初始化录音
 * @return {Promise}
 */
amr.initWithRecord();

事件

注意:事件不会叠加,也就是说,新注册的事件将覆盖掉旧的事件。

2022-09-26 更新: 现在支持解绑事件,只要传入 null,例如 amr.onPlay(null)

/**
 * 播放
 * @param {Function | null} fn
 */
amr.onPlay(function() {
  console.log('开始播放');
});
/**
 * 停止(包括播放结束)
 * @param {Function | null} fn
 */
amr.onStop(function() {
  console.log('停止播放');
});
/**
 * 暂停
 * @param {Function | null} fn
 */
amr.onPause(function() {
  console.log('暂停');
});
/**
 * (暂停状态中)继续播放
 * @param {Function | null} fn
 */
amr.onResume(function() {
  console.log('继续播放');
});
/**
 * 播放结束
 * @param {Function | null} fn
 */
amr.onEnded(function() {
  console.log('播放结束');
});
/**
 * 播放到结尾自动结束
 * @param {Function | null} fn
 */
amr.onAutoEnded(function() {
  console.log('播放自动结束');
});
/**
 * 开始录音
 * @param {Function | null} fn
 */
amr.onStartRecord(function() {
  console.log('开始录音');
});
/**
 * 结束录音
 * @param {Function | null} fn
 */
amr.onFinishRecord(function() {
  console.log('结束录音');
});

播放控制

/**
 * 播放(无视暂停状态)
 * @param {number?} startTime 可指定播放开始位置(秒,浮点数,可选)
 */
amr.play();
/**
 * 停止
 */
amr.stop();
/**
 * 暂停
 * @since 1.1.0
 */
amr.pause();
/**
 * 从暂停状态中继续播放
 * @since 1.1.0
 */
amr.resume();
/**
 * 整合 play() 和 resume(),若在暂停状态则继续,否则从头播放
 * @since 1.1.0
 */
amr.playOrResume();
/**
 * 整合 resume() 和 pause(),切换暂停状态
 * @since 1.1.0
 */
amr.pauseOrResume();
/**
 * 整合 play() 和 resume() 和 pause()
 * @since 1.1.0
 */
amr.playOrPauseOrResume();
/**
 * 跳转到音频指定位置,不改变播放状态(若停止状态则等同于 `play(time)`) 
 * @since 1.1.0
 * @param {Number} time 指定位置(秒,浮点数)
 */
amr.setPosition(12.34);
/**
 * 获取当前播放位置(秒) 
 * @since 1.1.0
 * @return {Number} 位置,秒,浮点数
 */
amr.getCurrentPosition();
/**
 * 是否正在播放
 * @return {boolean}
 */
amr.isPlaying();
/**
 * 是否暂停中
 * @since 1.1.0
 * @return {boolean}
 */
amr.isPaused();

录音控制

/**
 * 开始录音
 */
amr.startRecord();
/**
 * 结束录音,并把录制的音频转换成 AMR
 * @return {Promise}
 */
amr.finishRecord();
/**
 * 放弃录音
 */
amr.cancelRecord();
/**
 * 是否正在录音
 * @return {boolean}
 */
amr.isRecording();

其他

/**
 * 获取音频的时间长度(单位:秒)
 * @return {Number}
 */
amr.getDuration();
/**
 * 获取 AMR 文件的 Blob 对象(用于下载文件)
 * @return {Blob}
 */
amr.getBlob();
/**
 * 释放amr文件数据,释放pcm音频数据,停止录音释放录音数据,取消监听所有事件,对象作废
 * @since 1.1.4
 */
amr.destroy();
/**
 * 判断浏览器是否支持播放
 * 注意这是静态(static)方法
 * @since 1.1.0
 * @return {boolean}
 */
BenzAMRRecorder.isPlaySupported();
// 不是 amr.isPlaySupported();
/**
 * 判断浏览器是否支持录音
 * 注意这是静态(static)方法
 * @since 1.1.0
 * @return {boolean}
 */
BenzAMRRecorder.isRecordSupported();
// 不是 amr.isRecordSupported();

尚未完成的特性

  • 使用 Worker 编码解码 AMR。(v1.0.9)
  • 暂停播放功能。(v1.1.0)
  • 暂停录音功能。
  • 播放进度控制。(v1.1.0)
  • 浏览器兼容性检查(#9 #11)。(v1.1.0)

常见问题

- 初始化之后如何更换音频?

请重新执行 new BenzAMRRecorder() 创建新的对象,然后用新的音频去初始化。

旧的对象只要没有变量引用就会被浏览器作为垃圾回收内存。

如果你的应用本身比较吃内存,或者希望更快地让浏览器回收内存,可以对旧的对象执行一下 amr.destroy() (版本 1.1.4),这样这个对象内部所存储的音频数据和文件数据都会被设置为 null ,然后这个对象就彻底不能用了。

为什么不让旧的对象内部实现更换音频?

  1. 对象初始化时会决定该对象是用于录音或用于播放,重新初始化会让内部逻辑变得复杂。
  2. 本项目的主要用途是语音聊天,而不是音乐播放,所以项目架构设计成了“每一条语音消息对应一个 BenzAMRRecorder 对象”,可节省网络开销,多次播放音频也不消耗网络流量。
  3. 多个音频(对象)还可以同时混音播放。
  4. ^偷懒^。

- 关于跨域

这需要目标服务器(即存放amr文件的服务器)支持跨域,不是修改前端代码能解决的。

基本上如果服务器是CDN的话都能支持。如果不是CDN,那就请自行谷鸽百度一下如何让服务器支持跨域,或者找你们后端或运维同事帮忙。

- 采样率?

本项目仅支持 amr-nb 格式,这种格式只有一种采样率 8000Hz。因为amr这种格式是专门设计成用于人声录音的,这个采样率足以把人类日常说话的字词句录清楚。对于人类,只有强悍的女高音歌手才能尖叫出接近8000Hz的声音。

另有一种 amr-wb 格式,采样率是 16000Hz,提升采样率可以让人声从“听得清楚”升级成“听得舒服”。人类在讲话的时候会伴随一些呼吸声气流声,这些声音有时候只能用上高采样率才能录进去。

目前本项目不支持 amr-wb。

- 能支持 amr-wb 格式吗?

不打算支持,因为这会让包体积变大。本项目原本是为了配合微信做语音应用的,微信也没有用到 amr-wb。

已经有网友fork支持amr-wb了,在此感谢AcoWaves。

- Webpack 或 babel 打包出错

由于本人已经不参与音频相关的项目,目前暂时没时间Debug了。哪位大佬要是帮忙修复了,欢迎提PR。

2022-09-26 更新: 最近有点空,我用 create-react-app 创建了一个 React 初始项目,尝试把 BenzAMRRecorder 用于 React 。没有发现任何问题。

- 本项目与Benz有什么关系?

Benz 是我本人从中学用到现在的英文名字,与某汽车厂商完全无关

- 似乎好久没有更新了?

由于本人已经不参与音频相关的项目,目前暂时没时间做更新了。而且我个人感觉本项目也没什么重要的东西需要更新了。(项目的基础 amr.js 也是n年没有更新了。)欢迎大佬们提PR。

2022-09-26 更新: 做个小更新,主要试一试 Webpack 和 babel,当然我也没有手工地配置 Webpack 和 babel,就直接用脚手架 create-react-app 测试,然而用着很正常,没有发现问题。另外增加了事件取消绑定功能,以及增加一个好像没什么用的 destroy() 方法。

许可

MIT.

benz-amr-recorder's People

Contributors

benzleung avatar dependabot[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

benz-amr-recorder's Issues

请问如何在播放过程中点击按钮切换播放文件

您好!我在做一个聊天室,可能一个音频文件还没播放结束就会点击另外一条语音,播放另外一条文件,请问如何实现?
如果我使用
amr.initWithUrl('new file url.amr').then(function() {
amr.play();
});
amr.onEnded(function() {
alert('播放完毕');
})
就报错说arm已存在,如果我使用

var amr = new BenzAMRRecorder();
amr.initWithUrl('path/to/voice.amr').then(function() {
amr.play();
});
amr.onEnded(function() {
alert('播放完毕');
})
重新new 实例化一个,就提示arm不存在,好像new 下一行不能紧接着使用initWithUrl方法,请问如何处理比较好?能不能我个changeUrl方法呢

遇到amr音频时,当xhr.response返回的是audio/amr-wb时decode 解析报错,audio/amr 解析正常

如题,经过查阅,audio/amr-wb是宽带,audio/amr后者是窄带
AMR NB的语音带宽范围:300-3400Hz,8KHz采样
AMR WB的语音带宽范围: 50-7000Hz,16KHz采样
有没有什么比较好的处理方法呢?

以及,如果我想在源码基础上做一些更改,请问,哪些文件是必要的? 和demo.html 同级的 BenzAMRRecorder.js 我拿出来过,但是报了特别多的语法错误

vue使用标签引用法不生效

image
1,<script type="text/javascript" src="./BenzAMRRecorder.min.js"></script>这种方式引入后,无法使用new BenzAMRRecorder()
2,但是var BenzAMRRecorder = require('benz-amr-recorder')这种方式可以正常使用
3,另外,非vue项目,在原生html页面使用script标签引用可以正常使用

请大佬们指点迷津

android 上报错执行ffmpeg没权限

at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963)
Caused by: java.lang.IllegalStateException: convert amr to mp3 error:
at it.sauronsoftware.jave.AudioUtils.convert(AudioUtils.java:60)
at it.sauronsoftware.jave.AudioUtils.amrToMp3(AudioUtils.java:34)
at com.example.salemen.Recording.PhoneCallReceiver.amrToMp3(PhoneCallReceiver.java:317)
at com.example.salemen.Recording.PhoneCallReceiver.onOutgoingCallEnded(PhoneCallReceiver.java:208)
at com.example.salemen.Recording.PhoneCallReceiver.onReceive(PhoneCallReceiver.java:100)
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3793)
at android.app.ActivityThread.-wrap18(Unknown Source:0) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2100) 
at android.os.Handler.dispatchMessage(Handler.java:109) 
at android.os.Looper.loop(Looper.java:166) 
at android.app.ActivityThread.main(ActivityThread.java:7555) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:469) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963) 
Caused by: it.sauronsoftware.jave.EncoderException: java.io.IOException: Cannot run program "/data/user/0/com.example.salemen/cache/jave-1/ffmpeg": error=13, Permission denied
at it.sauronsoftware.jave.Encoder.encode(Encoder.java:830)
at it.sauronsoftware.jave.Encoder.encode(Encoder.java:712)
at it.sauronsoftware.jave.AudioUtils.convert(AudioUtils.java:58)
at it.sauronsoftware.jave.AudioUtils.amrToMp3(AudioUtils.java:34) 
at com.example.salemen.Recording.PhoneCallReceiver.amrToMp3(PhoneCallReceiver.java:317) 
at com.example.salemen.Recording.PhoneCallReceiver.onOutgoingCallEnded(PhoneCallReceiver.java:208) 
at com.example.salemen.Recording.PhoneCallReceiver.onReceive(PhoneCallReceiver.java:100) 
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3793) 
at android.app.ActivityThread.-wrap18(Unknown Source:0) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2100) 
at android.os.Handler.dispatchMessage(Handler.java:109) 
at android.os.Looper.loop(Looper.java:166) 
at android.app.ActivityThread.main(ActivityThread.java:7555) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:469) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963) 
Caused by: java.io.IOException: Cannot run program "/data/user/0/com.example.salemen/cache/jave-1/ffmpeg": error=13, Permission denied
at java.lang.ProcessBuilder.start(ProcessBuilder.java:1048)
at java.lang.Runtime.exec(Runtime.java:692)
at java.lang.Runtime.exec(Runtime.java:560)
at it.sauronsoftware.jave.FFMPEGExecutor.execute(FFMPEGExecutor.java:105)
at it.sauronsoftware.jave.Encoder.encode(Encoder.java:828)
at it.sauronsoftware.jave.Encoder.encode(Encoder.java:712) 
at it.sauronsoftware.jave.AudioUtils.convert(AudioUtils.java:58) 
at it.sauronsoftware.jave.AudioUtils.amrToMp3(AudioUtils.java:34) 
at com.example.salemen.Recording.PhoneCallReceiver.amrToMp3(PhoneCallReceiver.java:317) 
at com.example.salemen.Recording.PhoneCallReceiver.onOutgoingCallEnded(PhoneCallReceiver.java:208) 
at com.example.salemen.Recording.PhoneCallReceiver.onReceive(PhoneCallReceiver.java:100) 
at android.app.ActivityThread.handleReceiver(ActivityThread.java:3793) 
at android.app.ActivityThread.-wrap18(Unknown Source:0) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2100) 
at android.os.Handler.dispatchMessage(Handler.java:109) 
at android.os.Looper.loop(Looper.java:166) 
at android.app.ActivityThread.main(ActivityThread.java:7555) 
at java.lang.reflect.Method.invoke(Native Method) 
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:469) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:963) 
Caused by: java.io.IOException: error=13, Permission denied
at java.lang.UNIXProcess.forkAndExec(Native Method)
at java.lang.UNIXProcess.(UNIXProcess.java:133)
at java.lang.ProcessImpl.start(ProcessImpl.java:128)

手机上的录音文件转码失败

手机上的录音文件无法播放
53:1 Uncaught (in promise) DOMException: Unable to decode audio data
BenzAMRRecorder.js:30746 Uncaught (in promise) Error: Failed to decode.

[该录音为系统自动通话录音

小程序无法使用

image
image
如图 New对象的时候报错

代码是 let soundInstance = new BenzAMRRecorder();
然后报错
TypeError: Cannot read property 'AudioContext' of undefined
at BenzAMRRecorder.js?t=wechat&s=1612677238981&v=6bc5d1f35f8f610d9ca7773c0ee5478b:290
at BenzAMRRecorder.js?t=wechat&s=1612677238981&v=6bc5d1f35f8f610d9ca7773c0ee5478b:2
at BenzAMRRecorder.js?t=wechat&s=1612677238981&v=6bc5d1f35f8f610d9ca7773c0ee5478b:5
at require (VM5786 WAService.js:2)
at VM5786 WAService.js:2
at index.js? [sm]:6
at require (VM5786 WAService.js:2)
at :996:9
at doWhenAllScriptLoaded (:1175:21)
at Object.scriptLoaded (:1195:5)

最小化文件BenzAMRRecorder.min.js无法正常使用

提示this.te 不是个函数,检查了min文件发现,是把_playEmpty()函数替换成了te,但是_defineProperty仍然注册为_playEmpty,所以报错。
另外我尝试把this.te手动替换成this._playEmpty,这个错误就跳过去了,但是仍然有其他报错,所以这个min文件根本无法运行,能否重新打包?

initWithUrl一个amr链接报错_typeof is not defined

Uncaught ReferenceError: _typeof is not defined
at Object.open (8e8bdf9e-d4c0-4737-bebc-063804e23f6b:2)
at Object.createStandardStreams (8e8bdf9e-d4c0-4737-bebc-063804e23f6b:2)
at Object.init (8e8bdf9e-d4c0-4737-bebc-063804e23f6b:2)
at 8e8bdf9e-d4c0-4737-bebc-063804e23f6b:2
at callRuntimeCallbacks (8e8bdf9e-d4c0-4737-bebc-063804e23f6b:2)
at ensureInitRuntime (8e8bdf9e-d4c0-4737-bebc-063804e23f6b:2)
at doRun (8e8bdf9e-d4c0-4737-bebc-063804e23f6b:6)
at run (8e8bdf9e-d4c0-4737-bebc-063804e23f6b:6)
at 8e8bdf9e-d4c0-4737-bebc-063804e23f6b:6
at 8e8bdf9e-d4c0-4737-bebc-063804e23f6b:6

经常性不能录音

长按调initWithRecord方法进行初始化,在then回调里面调startRecord方法进行录音,大概过了5,6秒结束,经常性会出现无录音的情况,此时BenzAmrRecord对象如下。版本:1.1.3

_blob: Blob {size: 6, type: "audio/amr"}
_isInit: true
_isInitRecorder: true
_isPaused: false
_isPlaying: false
_onAutoEnded: null
_onCancelRecord: ƒ ()
_onEndCallback: ƒ ()
_onEnded: null
_onFinishRecord: ƒ ()
_onPause: null
_onPlay: null
_onResume: null
_onStartRecord: ƒ ()
_onStop: null
_pauseTime: 0
_playEmpty: ƒ ()
_rawData: Uint8Array(6) [35, 33, 65, 77, 82, 10]
_recorderControl: RecorderControl {_recorderStream: null, _recorderStreamSourceNode: MediaStreamAudioSourceNode, _recorder: null, _isRecording: false, _curSourceNode: AudioBufferSourceNode}
_runAMRWorker: ƒ (msg, resolve)
_samples: Float32Array []
_startCtxTime: 0
__proto__: Object

在react中使用报错

    const BenzAMRRecorder = require('benz-amr-recorder')

         <Button
          onClick={() => {
            var amr = new BenzAMRRecorder()
            amr
              .initWithUrl(
                'https://static.tuputech.com/api/image/original/cloud-api/storage-0831/2019-08-01/10/5d0b3fb7a9fe1ca9c4f20707/15646272568190.2911486649597441.amr'
              )
              .then(function () {
                amr.play()
              })
            amr.onEnded(function () {
              console.log('object')
              alert('播放完毕')
            })
          }}
        >
          点播放
        </Button>

会发送请求 拿到数据 可是amr.play()不会执行 报错

Uncaught TypeError: Cannot read property 'slice' of null
    at parseJSFunc (808055f6-876e-418e-aad5-6bdc5a02d6ca:602)
    at 808055f6-876e-418e-aad5-6bdc5a02d6ca:614
    at 808055f6-876e-418e-aad5-6bdc5a02d6ca:669
    at 808055f6-876e-418e-aad5-6bdc5a02d6ca:30010

好像是AMR报错

        function parseJSFunc(jsfunc) {
          var parsed = jsfunc.toString().match(sourceRegex).slice(1);  // 这句报错
          return {
            arguments: parsed[0],
            body: parsed[1],
            returnValue: parsed[2]
          };
        }

benz-amr-recorder如何重新初始化

有这样简单的需求,通过不同的url播放不同的arm文件,但是benz-amr-recorder已经痛殴url初始化了。无法再次初始化,不能实现类似音乐播放切换音乐的效果

播放音乐切换控制问题

@BenzLeung 感谢回复,音乐切换有两个细节问题
场景是这样的:我有多个播放按钮是异步获取音乐的url, 但是我只能播放某一个音乐:

  1. 点击当前音乐的播放按钮可以控制播放和暂停;
    2.点击别的音乐播放按钮需要停止之前的音乐并播放当前的音乐。
    直接new 对象的方式无法实现相互控制。

点击当前音频的播放按钮可以控制播放和暂停;

为什么我现在控制不了暂停

state ={
isPlay: false
}
  playAmrFile(url) {
    this.setState({
      isPlay: !this.state.isPlay
    }, () => {
      amr = new BenzAMRRecorder();
      amr.initWithUrl(url).then( () => {
        if(this.state.isPlay){
          amr.playOrPauseOrResume();
        } else {
          amr.stop()
        }
      });
    })
  }

如果播amr 正播放呢,我把这个页面销毁了,音频还在播放bug

如果播amr 正播放呢,我把这个页面销毁了,音频还在播放,除非我F5 刷新页面,
有没有别的处理方式,比如可以在 页面关闭时候调用amr 对象的 destroy() 方法类似的逻辑呢
或者有别的方法吗?

  // 我先定义了一个这个,用来接受 amr 对象
  const audioRef = useRef(); //audio标签Ref

  // 定义 amr 并 赋值给 audioRef.current
  const armOptions = {
      src: audioInfo.src,
      isloop: loop,
  };
  const amr = initArmObj(callBack, armOptions);
  audioRef.current = amr;

  // 当页面销毁时候手动置空
 
  useEffect(() => {
        return (() => {
            // 如果是amr 类型文件,存在一直播放bug
            if (ext === 'amr') {
                audioRef.current.stop();
            }

            // 销毁音频组件
            audioRef.current = null;
        });
    }, [ext]);
 
 

ios9不兼容

大佬, ios9这个插件会引起js加载的时候就报错
报这个错
SyntaxError: Unexpected identifier 'ctx'

我们开发的时候没有使用里面的录音功能,录音我们用的是微信的sdk,我们只用了里面的amr读取播放,大佬,能不能将功能拆分开哦?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.