标签:ntb class 消息 聊天室 style source sea otc glin
功能简介:
不需要借助百度的语音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"> 目标对象:<input type="text" id="to_user"> <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>
标签:ntb class 消息 聊天室 style source sea otc glin
原文地址:https://www.cnblogs.com/Dominic-Ji/p/9520879.html