语音一对一聊天

2018-08-26 17:26:40来源:博客园 阅读 ()

新老客户大回馈,云服务器低至5折

功能简介:

  不需要借助百度的语音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>

 

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:在for循环中动态拼接字符串和添加事件

下一篇:懒加载