qiuxiang / react-native-recording Goto Github PK
View Code? Open in Web Editor NEWReact Native audio recording module used for DSP with Android + iOS
License: MIT License
React Native audio recording module used for DSP with Android + iOS
License: MIT License
package.json
{
"name": "WebSokectTest",
"version": "0.0.1",
"private": true,
"scripts": {
"start": "node node_modules/react-native/local-cli/cli.js start",
"test": "jest"
},
"dependencies": {
"react": "16.0.0",
"react-native": "0.50.3",
"react-native-audio": "^3.5.0",
"react-native-fetch-blob": "^0.10.8",
"react-native-recording": "^0.2.0"
},
"devDependencies": {
"babel-jest": "21.2.0",
"babel-preset-react-native": "4.0.0",
"jest": "21.2.1",
"react-test-renderer": "16.0.0"
},
"jest": {
"preset": "react-native"
}
}
componentDidMount() {
//Recording.init()
Recording.initWithOptions({
bufferSize: 8192,
sampleRate: 16000,
bitsPerChannel: 16,
channelsPerFrame: 1
});
}
只要执行Recording.init()就会闪退
import React, { Component } from 'react'
import { View, Text, Button } from 'react-native'
import Recording from 'react-native-recording'
export default class Main extends Component {
componentDidMount() {
Recording.init({
bufferSize: 4096,
sampleRate: 44100,
bitsPerChannel: 16,
channelsPerFrame: 1,
})
Recording.addRecordingEventListener(data => console.log(data))
}
startRecord() {
Recording.start()
}
stoptRecord() {
Recording.stop()
}
render() {
return (
<View>
<Text>Melody</Text>
<Button title='record' onPress={() => { this.startRecord() }} />
<Button title='stop' onPress={() => { this.stoptRecord() }} />
</View>
)
}
I am using the Recording module to stream data to PC over websocket as below. But the data is getting sent only once. If I press start for the second time , keypress in sent to PC but no voice data sent as the eventlistener not getting called. What am i doing wrong here?
import React from 'react';
import {Component,Text,View,Button, Alert } from 'react-native';
import Recording from 'react-native-recording';export default class VoiceScreen extends React.Component {
constructor(){
super();
this.state={
status:true
}
}
componentDidMount(){
//await this.checkPermission();
Recording.init({bufferSize: 640, sampleRate: 16000, bitsPerChannel: 16, channelsPerFrame: 1, }) Recording.addRecordingEventListener(this.DataHandler); ws.onmessage=(m)=> { console.log(m.data +"status "+this.state.status); if(m.data=='READY') { this.startVoice(); } else { this.stopVoice(); } }
}
startVoice(){
Recording.start();
}stopVoice()
{
Recording.stop();
}DataHandler=(data)=>{
console.log(" Sending auido data of len "+data.length*2); var pcm_len = data.length*2; //data.unshift(pcm_len>>8); data.unshift(pcm_len); data.unshift(0x03); var view = new Uint16Array(data); //var view1 = new Uint8Array(view); ws.send(view); data.pop(); data.pop();
}
sendVoiceKeyPress(){
cmd = []; cmd.push(0x04); cmd.push(0x00); cmd.push(0x05); cmd.push(0x00); cmd.push(0x56); cmd.push(0x4F); cmd.push(0x49); cmd.push(0x43); cmd.push(0x45); start_speech = new Uint8Array(cmd); ws.send(start_speech); this.setState({status:false});
}
sendVoiceKeyRelease(){
this.stopVoice();
cmd = [];
cmd.push(0x05);
cmd.push(0x00);
cmd.push(0x05)
cmd.push(0x00);
cmd.push(0x56);
cmd.push(0x4F);
cmd.push(0x49);
cmd.push(0x43);
cmd.push(0x45);
stop_speech = new Uint8Array(cmd);
ws.send(stop_speech);
this.setState({status:true});}
componentWillUnmount() {
//Recording.stop()
}
render() {
return( <View> {this.state.status?<Button title='start' onPress={()=>this.sendVoiceKeyPress()}/>:<Button title='stop' onPress={()=>this.sendVoiceKeyRelease()}/>} </View> )
}
}
`
This line
AudioQueueNewInput(&description, inputCallback, (__bridge void *) self, NULL, NULL, 0, &_queue);
is causing the error EXC_BAD_ACCESS code=257 to be thrown whenever I refresh while debugging.
I used your module to record audio on a galaxy S4 device, and exported the audio to a .dat file. I used matlab to play the file, and was surprised to hear how noisy the audio was. Any ideas? Below is my code...
index.js top
import Recording from 'react-native-recording';
import RNFS from 'react-native-fs';
import {testAudioRecording} from './helper';
index.js component
Recorder = () => {
this.state.isRecording?console.log('Start recording...'):console.log('Stop recording...');
this.RecorderTask(this.state.isRecording);
this.state.isRecording?Recording.start():Recording.stop();
}
RecorderTask = (state) => {
if(state){
this.recordingdata = [];
Recording.init({
bufferSize: 4096,
//sampleRate: 8000, // for Emulator?
sampleRate: 44100, // for Actual Device
bitsPerChannel: 16,
channelsPerFrame: 1,
});
Recording.addRecordingEventListener(datab => this.recordingdata.push(datab));
}else{
testAudioRecording(this.recordingdata);
//Recording.removeRecordingEventListener();
}
}
helper.js component
export function testAudioRecording(data){
const root = RNFS.ExternalStorageDirectoryPath+'/Download';
//const root = RNFS.DocumentDirectoryPath+'/Download';
const path1 = root+'/recording-test-data.dat';
RNFS.writeFile(path1, data).then((success) => {
return true;
}).catch((err) => {
return false;
});
}
Attached below is a sample recording (raw data) of the song 'Give Me Everything' by Pitbull. I had to change the file extension to .txt in order to upload it here.
recording-test-data.txt
The same build worked two weeks ago. But when we tested it today it won't fire callbacks on iOS.
Actually, it will fire just once with an empty array.
It happens on multiple versions of iOS (we checked 14.0, 14.5, and 15 beta). (at least 14.0 worked two weeks ago). And I cannot reproduce it in ios emulator.
Are you experiencing similar issues?
I ran below code and set listener callback is called every 2.5 seconds. Strangely, two lister callbacks are called and one of which always returns zeros. Does anyone know this situation and solution? I ran android physical device connected to MacOS via USB cable.
import React, {useEffect} from 'react';
import {PermissionsAndroid, Text} from 'react-native';
import Recording from 'react-native-recording';
const App = () => {
const requestPermission = async () => {
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
]);
};
requestPermission();
Recording.init({
bufferSize: 24000 * 2.5,
sampleRate: 24000,
bitsPerChannel: 16,
channelsPerFrame: 1,
});
useEffect(() => {
console.log('start effect');
const listener = Recording.addRecordingEventListener((data: number[]) => {
console.log(data.slice(0, 100));
Recording.start();
return () => {
console.log('clean up');
Recording.stop();
listener.remove();
};
}, []);
return (<Text>aaa</Text>)
Standard output from terminal
[Tue Oct 20 2020 17:32:37.599] LOG start effect
[Tue Oct 20 2020 17:32:39.439] LOG [17, 3, 11, 46, 3, -13, 9, -4, -9, -10, -19, -39, -22, -27, -48, -48, -57, -27, -14, -40, -14, 18, -9, 8, -5, -19, 6, -25, -9, 18, 22, 32, 75, 82, 46, 46, 17, 4, -26, -40, -41, -83, -60, -105, -119, -111, -127, -104, -145, -134, -101, -107, -128, -154, -175, -160, -140, -154, -121, -107, -141, -117, -99, -152, -142, -138, -160, -139, -144, -144, -126, -124, -138, -116, -134, -122, -93, -121, -102, -110, -123, -105, -133, -188, -141, -156, -189, -142, -158, -105, -93, -134, -118, -135, -152, -108, -95, -106, -72, -104]
[Tue Oct 20 2020 17:32:40.333] LOG [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[Tue Oct 20 2020 17:32:41.936] LOG [47, 15, 29, 35, 4, 14, 35, 40, 34, 39, 35, 25, 59, 77, 57, 51, 54, 35, 34, 43, 21, 33, 47, 48, 50, 65, 86, 110, 134, 136, 136, 142, 164, 163, 141, 120, 91, 72, 74, 50, 37, 64, 58, 50, 71, 81, 72, 55, 43, 40, 18, -7, 1, -26, -48, -24, -60, -69, -62, -85, -80, -80, -93, -105, -108, -125, -126, -126, -124, -118, -146, -157, -134, -140, -117, -118, -124, -80, -117, -87, -83, -128, -101, -139, -142, -125, -138, -132, -140, -135, -129, -120, -97, -85, -80, -92, -88, -113, -129, -86]
[Tue Oct 20 2020 17:32:42.781] LOG [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[Tue Oct 20 2020 17:32:44.407] LOG [35, 49, 49, 7, 15, 43, 23, 24, 47, 72, 103, 98, 91, 96, 72, 74, 102, 90, 84, 103, 95, 126, 136, 120, 144, 122, 107, 110, 96, 93, 100, 91, 76, 77, 71, 81, 76, 48, 37, 44, 48, 56, 56, 65, 66, 61, 81, 69, 66, 62, 34, 20, -6, -12, -6, 0, 7, 12, 50, 65, 93, 99, 127, 143, 115, 104, 77, 94, 73, 91, 101, 69, 114, 121, 113, 143, 165, 132, 166, 169, 115, 135, 111, 83, 70, 43, 4, 24, 44, 28, 44, 34, 35, 60, 48, 21, 25, 10, -17, 7]
[Tue Oct 20 2020 17:32:45.444] LOG [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[Tue Oct 20 2020 17:32:46.957] LOG [-10, -6, -32, -37, -50, -48, -54, -69, -38, -35, -21, -15, -7, -6, 0, -8, -34, -13, -12, -10, -19, -36, -16, -10, -7, -1, -25, 1, 15, 23, 44, 20, 35, 34, 34, 13, -2, 36, 40, 69, 89, 77, 76, 93, 84, 58, 58, 40, 36, 44, 53, 87, 95, 109, 139, 140, 148, 139, 132, 121, 110, 110, 101, 106, 114, 148, 167, 176, 187, 199, 195, 166, 182, 174, 172, 191, 180, 202, 224, 209, 209, 197, 207, 214, 194, 232, 216, 204, 203, 172, 187, 211, 196, 206, 251, 235, 243, 260, 247, 249]
[Tue Oct 20 2020 17:32:47.837] LOG [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
[Tue Oct 20 2020 17:32:49.432] LOG [-197, -168, -208, -172, -179, -190, -146, -163, -143, -144, -189, -177, -163, -201, -184, -142, -125, -109, -95, -86, -108, -119, -141, -148, -131, -114, -95, -59, -32, -32, -27, -11, -24, -46, -29, -35, -20, -18, -21, 10, 15, 18, 44, 58, 40, 71, 73, 69, 87, 84, 101, 75, 88, 99, 85, 96, 87, 78, 82, 93, 70, 109, 124, 68, 78, 53, 34, 74, 51, 38, 71, 65, 47, 63, 35, 22, 46, 14, 17, 18, 28, 9, -12, 23, -11, -24, 26, 17, 11, 40, 28, 0, -3, -5, -42, -11, -13, -28, -7, -28]
[Tue Oct 20 2020 17:32:50.288] LOG [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
Dependency
"react": "16.13.1",
"react-native": "0.63.3",
"react-native-recording": "^0.5.1"
RT,如何处理?
My goal is to send a data array with size 5.17 KiB/s to a WebSocket.
I have not tried it yet, currently I tried to save the audio to a file. I use RNSaveAudio to save the audio file. I also use react-native-fs to get the app's folder path.
My expected result is the file should be around 5 - 6 kB for 1 seconds of audio.
My actual result is: 8236 bytes for 93 milliseconds (roughly 0,093 seconds) of audio. I tried to change the sampleRate
to 8000. I found the data size to be 2 - 3 times larger compared to Opus Voice with bit rate 5.17 KiB/s and sampling rate 8 kHz.
Steps to reproduce:
let audioInt16: number[] = [];
let listener;
React.useEffect(() => {
// eslint-disable-next-line react-hooks/exhaustive-deps
listener = Recording.addRecordingEventListener((data: number[]) => {
console.log('record', data.length);
// eslint-disable-next-line react-hooks/exhaustive-deps
audioInt16 = audioInt16.concat(data);
});
return () => {
listener.remove();
};
});
const startAsync = async () => {
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
]);
Recording.init({
bufferSize: 4096,
sampleRate: 44100,
bitsPerChannel: 16,
channelsPerFrame: 1,
});
Recording.start();
};
const saveAudio = async () => {
const promise = await RNSaveAudio.saveWav(path, audioInt16);
console.log('save audio', promise, path);
};
const playAudio = () => {
if (player.canPrepare || player.canPlay) {
player.prepare((err) => {
if (err) {
console.log(err);
}
console.log('play audio', player.duration);
player.play();
});
}
};
for (let d = 0; d < this.globalBuffer.length; d++) {
rms += this.globalBuffer[d] * this.globalBuffer[d];
}
rms = Math.sqrt(rms / this.globalBuffer.length);
I use this algorithm which called root-mean-square It basically calculates the amount of signal in the buffer but when there is no sound it gives values which are more than 0.
My question: What is the proper way to determine input audio level in react native by using this library?
Note: I'm trying to implement this tuner to my react native app it is written with javascript web audio api
I think I need to use AnalyserNode in react native but how?
https://developer.mozilla.org/en-US/docs/Web/API/AnalyserNode
Hi there,
I am getting this error:
[Unhandled promise rejection: TypeError: null is not an object (evaluating 'Recording.init')]
at node_modules/react-native-recording/lib/index.js:14:30 in default.init
at components/AudioTest.tsx:31:18 in recordSound
In AudioTest.tsx
I just have a button that calls recordSound
(basically copied from the README):
import Recording from "react-native-recording";
...
async function recordSound() {
await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.RECORD_AUDIO,
]);
Recording.init({
bufferSize: 4096,
sampleRate: 44100,
bitsPerChannel: 16,
channelsPerFrame: 1,
});
const listener = Recording.addRecordingEventListener((data) =>
console.log(data)
);
Recording.start();
// stop recording
Recording.stop();
listener.remove();
}
Can you tell me what I am doing wrong?
I am using expo
on Android
version "react-native-recording": "^0.5.1",
I want to dump the audio samples I am getting into a file and later play them with Audacity. I am unable to do that. Actually , I want to send them over websocket ,but before that I want to dump them to a file and check with Audacity. Please let me know, how can I achieve this?
I'm getting this warning when running an app with this library:
warn The following packages use deprecated "rnpm" config that will stop working from next release:
To compile this properly, you may have to manually link the module. To do this:
go to android\settings.gradle
and add the lines
include ':react-native-recording'
project(':react-native-recording').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-recording/lib/android')
then go to android\app\src\main\java\com\...\MainApplication.java
and add the following lines
import cn.qiuxiang.react.recording.RecordingPackage;
as an import statement, and
new RecordingPackage()
under the new MainReactPackage()
line in the protected List<ReactPackage> getPackages() {
method. Finally, open android\app\build.gradle
and add
compile project(':react-native-recording')
inside of dependencies {
, then navigate to your project directory and enter cd android && gradlew
in cmd (windows).
Hope this helps someone!
Hello, how can implement playing of recorded audio on another device, I want to send array through the socket connection.
When I run a recording instance on my iPhone, my react-native UI gets blocked. It seems to me that since events are generated on incoming data from the audio codec, and the events are dispatched to the main thread, my react program gets stuck dealing with the recording data, instead of doing other things.
For instance, when I add the following lines of code Recording.addRecordingEventListener(datab => this.circularBuff.enqueue(datab));
which esentially adds data to a buffer, I am not able to trigger the Recording.Stop()
method from my UI with touch input. On android, there is a lag after I try and stop a recording.
My goal is to be able to detect an impulse from a small amount of buffered data using JS.
i got error when first trying to use this library based on example.
startRecording() called on an uninitialized AudioRecord
handlerStart() {
Recording.init({
bufferSize: 4096,
sampleRate: 44100
});
Recording.start();
Recording.on('recording', data => {
console.log(data)
})
}
render() {
return (
<View>
<Text onPress={this.handlerStart}>Recording</Text>
</View>
);
}
Hello, first of all thank you for the wonderful library! I am making an app which needs DSP and this has been such a life saver.
I'm having an issue with the recorder. Here is a high level of what the app is should be doing:
In step 3, I am getting nothing sent to the recorder's event listener (specifically, one empty buffer ( [] ) upon starting recording, and another upon ending recording)
Here is my code:
this.Recorder = require('react-native-recording').default;
this.Recorder.init({
bufferSize: constants.bufferSize,
sampleRate: constants.sampleRate,
bitsPerChannel: constants.bitsPerChannel,
channelsPerFrame: constants.channelsPerFrame,
});
this.Listener = this.Recorder.addRecordingEventListener((data) => {
console.log('New data!', data.length)
});
this.Recorder.start();
this.Recorder.stop();
this.Recorder = null;
this.Listener.remove();
this.Listener = null;
let sound = new Player(soundTypeFiles[soundType], {autoDestroy: true});
sound.volume = 0.5;
sound.play(sound.destroy());
The first run of recording returns buffers as expected. The sound plays as expected. However, when I try to record audio again, here is my console:
Start recording
New data!, 0
...nothing
Stop recording
New data!, 0
This is fully functional on android, and I'm not sure what to do on this issue. Any help is appreciated :)
I get the error "TypeError: null is not an object (evaluating 'Recording.init')" during
useEffect(() => {
Recording.init({
bufferSize: 4096,
sampleRate: 44100,
bitsPerChannel: 16,
channelsPerFrame: 1,
});
})
Please help.
export default {
// TODO: params check
init: (options: {
bufferSize: number,
sampleRate: number,
bitsPerChannel: 8 | 16,
channelsPerFrame: 1 | 2,
}) => Recording.init(options),
start: () => Recording.start(),
stop: () => Recording.stop(),
addRecordingEventListener: listener => eventEmitter.addListener('recording', listener)
}
is not working on the 0.62.2
fix this PLEASE
when I am Installing react-native-recording latest version and build and run app it gives error native module cannot be null in ios. Please help me what I am doing wrong?
Thanks in advance
How to create a file? Or do I recover the recorded file?
I am facing this error with react-native version 0.57.5. With latest version 0.60.3 its working fine. I am not sure how to fix this . Please let me know how to fix this.
Recording.init(16000, 8192)
Recording.start()
Recording.on('recording', (data) => {
this.ws.send(JSON.stringify({
stream_type: 'array',
stream: data,
status: 'process'
}))
})
同样的代码在安卓和IOS模拟器运行都没问题,IOS真机会报错
Sending recording
with no listeners registered.
[tid:com.apple.coreaudio.AQClient][RCTEventEmitter.m:54] Sending `recording` with no listeners registered.
2017-12-20 09:49:45.282081+0800 OralRn[10985:3006463] Sending `recording` with no listeners registered.
IOS版本 11.2
机型 iphone7
RN版本 0.50.3
When the app goes to background the the recording stops, how can we enable recording even if app is in background mode?
Thanks @qiuxiang
Its not working in IOS for react-native version 0.62❌ /Users/dijuptuladhar/Project/react-native/tunner/node_modules/react-native-recording/lib/ios/Recording.h:2:9: 'React/RCTEventEmitter.h' file not found
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.