最近在做社交功能,需要收发语音,所以就仿照微信做了一个语音录制功能
使用的是react-native-audio
GitHub地址:https://github.com/jsierles/react-native-audio
配置按照GitHub上配置就可以,挺好配置的
iOS支持的编码格式:lpcm, ima4, aac, MAC3, MAC6, ulaw, alaw, mp1, mp2, alac, amr
Android支持的编码:aac, aac_eld, amr_nb, amr_wb, he_aac, vorbis
简单说下我遇到的问题,android上录制的在ios上不能播放最后发现录制的语音设置参数少设置了
最后把录制格式设定为如下android和ios问题完美解决
AudioRecorder.prepareRecordingAtPath(audioPath, {
SampleRate: 22050,
Channels: 1,
AudioQuality: 'Low',
AudioEncoding: 'aac',
OutputFormat: 'aac_adts',
});
效果图如下:
总体思路就是把下面的小方块注册为手势模块去监听用户手势的变化,然后在state里面设置一些参数根据手势的变化给用户反馈
import {AudioRecorder, AudioUtils} from 'react-native-audio';
/*
this.audioPath
注意这个是你录音后文件的路径+文件名,
可以使用react-native-audio下的AudioUtils路径也可以使用其他路径,
如果名称重复会覆盖掉原有的录音文件
*/
this.audioPat = AudioUtils.DocumentDirectoryPath + '/test.aac', //路径下的文件名
this.state = {
actionVisible: false,
paused: false,
recordingText: "",
opacity: 'white',
recordingColor: "transparent",
text: I18n.t('message.Chat.Voice.holdToTalk'),
currentTime: null, //开始录音到现在的持续时间
recording: false, //是否正在录音
stoppedRecording: false, //是否停止了录音
finished: false, //是否完成录音
hasPermission: undefined, //是否获取权限
}
componentDidMount() {
this._checkPermission().then((hasPermission) => {
this.setState({ hasPermission });
if (!hasPermission) {
alert('您禁止了权限,这将导致语音功能无法使用')
return
};
this.prepareRecordingPath(this.audioPath);
AudioRecorder.onProgress = (data) => {
this.setState({
currentTime: Math.floor(data.currentTime)
}, () => {
if (this.state.currentTime >= maxDuration) {
alert(I18n.t('message.Chat.Voice.speakTooLong'))
this._cancel(true)
}
});
};
AudioRecorder.onFinished = (data) => {
// Android callback comes in the form of a promise instead.
if (Platform.OS === 'ios') {
this._finishRecording(data.status === "OK", data.audioFileURL);
}
};
});
this.Gesture = {
onStartShouldSetResponder: (evt) => true,
onMoveShouldSetResponder: (evt) => true,
onResponderGrant: (evt) => {
this.setState({
opacity: "#c9c9c9",
recordingText: I18n.t('message.Chat.Voice.fingerStroke'),
text: I18n.t('message.Chat.Voice.releaseEnd'),
icon: "ios-mic",
recordingColor: 'transparent'
}, _ => RecordView.show(this.state.recordingText, this.state.recordingColor, this.state.icon));
this._record();
},
onResponderReject: (evt) => {
},
onResponderMove: (evt) => {
if (evt.nativeEvent.locationY < 0 ||
evt.nativeEvent.pageY < this.recordPageY - UpperDistance) {
if (this.state.recordingColor != 'red') {
this.setState({
recordingText: I18n.t('message.Chat.Voice.loosenFingers'),
recordingColor: 'red',
icon: "ios-mic-off"
}, _ => RecordView.show(this.state.recordingText, this.state.recordingColor, this.state.icon));
}
} else {
this.setState({
recordingText: I18n.t('message.Chat.Voice.fingerStroke'),
recordingColor: 'transparent',
icon: "ios-mic"
}, _ => RecordView.show(this.state.recordingText, this.state.recordingColor, this.state.icon));
}
},
onResponderRelease: (evt) => {
this.setState({
opacity: "white",
text: I18n.t('message.Chat.Voice.holdToTalk')
});
RecordView.hide();
let canceled;
if (evt.nativeEvent.locationY < 0 ||
evt.nativeEvent.pageY < this.recordPageY) {
canceled = true;
} else {
canceled = false;
}
this._cancel(canceled)
},
onResponderTerminationRequest: (evt) => true,
onResponderTerminate: (evt) => {
},
};
}
render() {
return (
<View style={{ flex: 1 }}>
<View style={styles.Box}>
<View
ref={(record) => {
this.record = record
}}
{...this.Gesture} // 注册为手势组件
style={{
flex: 1,
alignItems: "center",
justifyContent: "center",
backgroundColor: this.state.opacity
}}
onLayout={() => this.handleLayout()}
>
<Text>{this.state.text}</Text>
</View>
</View>
</View>
)
}
上面弹出层的浮框实现为
使用的是一个三方库teaset
GitHub地址:https://github.com/rilyu/teaset
class RecordView {
static key = null;
static show(text, color, icon) {
if (RecordView.key) RecordView.hide()
RecordView.key = Toast.show({
text: (
<Text style={[styles.textStyles, { backgroundColor: color }]}>
{text}
</Text>
),
icon: color == 'red'
? <Image source={ic_ch3x} style={styles.imageStyles} />
: icon == 'short'
?
<Image source={SHORT4} style={styles.imageStyles} />
:
<Icon name={'ios-mic'} style={{ fontSize: 45, color: "white" }} />,
position: 'center',
duration: 1000000,
});
}
static hide() {
if (!RecordView.key) return;
Toast.hide(RecordView.key);
RecordView.key = null;
}
}
网友评论