功能簡介: 不需要藉助百度的語音SDK即可完成,只需要通過前端語言利用頁面獲取用戶語音直接將語音數據發送給後端保存,之後通過條件判斷再將保存好的語言文件地址發送給目標用戶,藉此即可完成用戶之間的單點通信 前端代碼 ...
功能簡介:
不需要藉助百度的語音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>