语音一对一聊天

Posted dominic-ji

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了语音一对一聊天相关的知识,希望对你有一定的参考价值。

功能简介:

  不需要借助百度的语音SDK即可完成,只需要通过前端语言利用页面获取用户语音直接将语音数据发送给后端保存,之后通过条件判断再将保存好的语言文件地址发送给目标用户,借此即可完成用户之间的单点通信

from flask import Flask,render_template,request,jsonify,send_file
from geventwebsocket.websocket import WebSocket
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import json
import os
import uuid
app=Flask(__name__)

@app.route(/,strict_slashes=False)
def temp():
    return render_template(单聊.html)

#提供给前端音频标签获取音频文件路由api
@app.route(/get_file/<filename>)
def get_file(filename):
    file =os.path.join(audio,filename)
    return send_file(file)

user_dict={}
#获取客户端用户名
@app.route(/ws/<username>,strict_slashes=False)
def index(username):
    while True:
        user_socket=request.environ.get(wsgi.websocket) # type:WebSocket
        if user_socket==None:
            return 不要给我发http请求了,老子这里只认websocket请求
        user_dict[username]=user_socket
        file_name=""
        user_json=""
        while True:
            try:
                #获取客户端数据
                user_msg=user_socket.receive()
                #如果是音频文件
                if type(user_msg) == bytearray:
                    #存放到audio文件下
                    file_name = f"{uuid.uuid4()}.wav"
                    file_name_path = os.path.join(audio,file_name)
                    with open(file_name_path,wb)as f:
                        f.write(user_msg)
                else:
                    #否则则是正常的文本数据,直接序列化即可,这个主要是用来展示消息发出者是谁
                    user_json = json.loads(user_msg)
                #必须获取到音频数据和消息发出者信息后
                if file_name and user_json:
                    #把存放数据的文件路径和发送者姓名传给被交流者
                    send_msg={
                        "send_msg":file_name,
                        "send_user":username
                    }

                    to_user_socket=user_dict.get(user_json.get(to_user))
                    to_user_socket.send(json.dumps(send_msg))
                    #将变量清空
                    file_name=""
                    user_json=""
            except Exception as a:
                print(a)
                user_dict.pop(username)
                break

if __name__ == __main__:
    http_server=WSGIServer((127.0.0.1,8000),app,handler_class=WebSocketHandler)
    http_server.serve_forever()

前端代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link href="https://cdn.bootcss.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">

</head>
<body>
<nav class="navbar navbar-inverse">
    <div class="container-fluid">
        <!-- Brand and toggle get grouped for better mobile display -->
        <div class="navbar-header">
            <button type="button" class="navbar-toggle collapsed" data-toggle="collapse"
                    data-target="#bs-example-navbar-collapse-1" aria-expanded="false">
                <span class="sr-only">Toggle navigation</span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
                <span class="icon-bar"></span>
            </button>
            <a class="navbar-brand" href="#">Brand</a>
        </div>

        <!-- Collect the nav links, forms, and other content for toggling -->
        <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
            <ul class="nav navbar-nav">
                <li class="active"><a href="#">Link <span class="sr-only">(current)</span></a></li>
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">One more separated link</a></li>
                    </ul>
                </li>
            </ul>
            <form class="navbar-form navbar-left">
                <div class="form-group">
                    <input type="text" class="form-control" placeholder="Search">
                </div>
                <button type="submit" class="btn btn-default">Submit</button>
            </form>
            <ul class="nav navbar-nav navbar-right">
                <li><a href="#">Link</a></li>
                <li class="dropdown">
                    <a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true"
                       aria-expanded="false">Dropdown <span class="caret"></span></a>
                    <ul class="dropdown-menu">
                        <li><a href="#">Action</a></li>
                        <li><a href="#">Another action</a></li>
                        <li><a href="#">Something else here</a></li>
                        <li role="separator" class="divider"></li>
                        <li><a href="#">Separated link</a></li>
                    </ul>
                </li>
            </ul>
        </div><!-- /.navbar-collapse -->
    </div><!-- /.container-fluid -->
</nav>
<div class="panel panel-primary">

    <div class="panel-heading">
        <h3 class="panel-title">聊天室</h3>
    </div>
    <div class="panel-body">
        <audio src="" id="player" autoplay="autoplay" controls></audio>
        <br>
        用户名:<input type="text" id="username">&nbsp;
        目标对象:<input type="text" id="to_user">&nbsp;<button class="btn btn-info" id="create_link"
                                                           onclick="create_link()">创建链接
    </button>
        <div id="chat_window" style="width: 400px;height: 300px;">

        </div>
        <br>
        <div>
            <button onclick="start_rec()">录音</button>
            <button onclick="stop_rec()">发送</button>
        </div>
    </div>
</div>
<script type="application/javascript" src="Recorder.js"></script>
<script type="application/javascript">
    var url = ws://127.0.0.1:8000/ws/;
    var ws = null;

    function create_link() {
        var username = document.getElementById(username);
        ws = new WebSocket(url + username.value);

        ws.onmessage = function (server_msg) {
            msg = JSON.parse(server_msg.data);
            create_chat(y, msg);

        };
    }
    function listen() {
            //将服务端返回的消息展现到音频播放标签中
            var player =document.getElementById(player);
            player.src=http://127.0.0.1:8000/get_file/+msg.send_msg
    }

    function create_chat(self, content) {
        if (self == w) {
            self = right;
            var spantag = document.createElement(span);
            spantag.innerText = content.send_msg;
            var spantag1 = document.createElement(span);
            spantag1.innerText = :我;
        } else {
            self = left;
            var spantag = document.createElement(span);
            spantag.innerText = content.send_user+:;
            var spantag1 = document.createElement(span);
            spantag1.innerHTML = "<button class=‘btn btn-primary‘ onclick=‘listen()‘>收听消息</button>";
        }
        var divtag = document.createElement(div);
        divtag.style = text-align: + self;

        divtag.appendChild(spantag);
        divtag.appendChild(spantag1);
        var chat_window = document.getElementById(chat_window);
        chat_window.appendChild(divtag);
    }

    var rec = null;
    var audio_content = new AudioContext();

    navigator.getUserMedia = (
        navigator.getUserMedia ||
            navigator.webkitGetUserMedia ||
            navigator.mozGetUserMedia ||
            navigator.msGetUserMedia
    );

    navigator.getUserMedia({audio:true},create_stream,function (error) {
        console.log(error)
    });
    function create_stream(stream){
      var stream_input = audio_content.createMediaStreamSource(stream);
      rec = new Recorder(stream_input);
    }
    function start_rec(){
        rec.record();
    }
    function stop_rec(){
        rec.stop();
        get_audio();
        rec.clear()
    }

    function get_audio() {
        rec.exportWAV(function (wav_file) {
            var to_user = document.getElementById(to_user);
            send_msg_json = {
                to_user:to_user.value
            };
            ws.send(JSON.stringify(send_msg_json));
            var s_msg = {send_msg:"语音消息"};
            create_chat(w,s_msg);
            ws.send(wav_file);
        })
    }

</script>
</body>
</html>

 

以上是关于语音一对一聊天的主要内容,如果未能解决你的问题,请参考以下文章

Javascript 中的 Agora 一对一语音通话并提供通知

HTML5实时语音通话聊天,MP3压缩传输3KB每秒

基于WebRtc实现安卓视频一对一聊天

语音聊天app开发如何进行代码分析

Epic将向开发者提供免费反作弊开发工具

如何优雅的用Python玩转语音聊天机器人