美文网首页React Native开发
React-Native实现仿微信发送语音

React-Native实现仿微信发送语音

作者: 学生黄哲 | 来源:发表于2019-07-05 16:11 被阅读520次

最近在做社交功能,需要收发语音,所以就仿照微信做了一个语音录制功能

使用的是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;
    }
}

相关文章

网友评论

    本文标题:React-Native实现仿微信发送语音

    本文链接:https://www.haomeiwen.com/subject/lylehctx.html