1. 程式人生 > >基於websocket的單聊.群聊

基於websocket的單聊.群聊

array mps ali rev ble round 500px ech process

關於ai.baidu.com的 代碼:

#########################################核心代碼##############################################
from aip import AipNlp, AipSpeech
import os
from uuid import uuid4
import go_tuling

APP_ID = "15217709"
API_KEY = "eNiP5QUsgBh6QwpbNv8Qmsy3"
SECRET_RET = "gwhM3wDo0Kjjd1PDIxqqW4Bfex10Y4f3"

client = AipSpeech(APP_ID, API_KEY, SECRET_RET)
nlp_client = AipNlp(APP_ID, API_KEY, SECRET_RET)


# 讀取文件
def get_file_content(filePath):
    # 格式轉換將其他格式的文件轉換成pcm文件
    os.system(f"ffmpeg -y -i {filePath} -acodec pcm_s16le -f s16le -ac 1 -ar 16000 {filePath}.pcm")
    with open(f"{filePath}.pcm", "rb")as fp:
        # 返回這個文件
        return fp.read()


# 音頻變文本
def audio2text(filename):
    print("1", filename)
    # 是被本地文件
    res = client.asr(get_file_content(filename), "pcm", 16000, {
        "dev_pid": 1536,
    })
    print(res.get("result")[0])
    return res.get("result")[0]


# 文本變音頻
def text2audio(A):
    result = client.synthesis(A, "zh", 1, {
        "per": 4,
        "pit": 8,
        "spd": 4,
        "vol": 5,
    })
    if not isinstance(result, dict):
        # 獲取文件的文件名
        filename = f"{uuid4()}.mp3"
        # 文件的路徑
        filepath = os.path.join("audios", filename)
        with open(filepath, "ab") as f:
            f.write(result)
        # 返回這個文件的名字
        return filename


# 獲取到用戶輸入的響應文件
def my_nip(Q):
    # 判斷用戶輸入的
    if nlp_client.simnet(Q, "你叫什麽名字").get("score") >= 0.7:
        A = "我的名字叫雪人"
    else:
        # 獲取圖靈返回的文字
        A = go_tuling.tl(Q, "yuebanwan")

    # 返回這個圖靈反應的文件
    return A

調用圖靈的代碼:

import requests
#########################################基本配置##########################
url = "http://openapi.tuling123.com/openapi/api/v2"

data_dict = {
    "reqType": 0,
    "perception": {
        "inputText": {
            "text": "北京"
        },
    },
    "userInfo": {
        "apiKey": "96dfe320eec549519c5168093f93b2dc",
        "userId": "yuebanwan"
    }
}


##################################執行函數#########################################
def tl(text, uid):
    # 給字典賦值text,這個text是傳過來用戶輸入的內容
    data_dict["perception"]["inputText"]["text"] = text
    # 並給字典表名是哪個用戶發來的請求
    data_dict["userInfo"]["userInfo"] = uid
    # 把消息數據返回給圖靈,圖靈並返回響應結果
    res = requests.post(url, json=data_dict)
    # 調用json方法把數據轉成json格式的數據
    res_json = res.json()
    # 把圖靈響應的數據
    return res_json.get("results")[0]["values"]["text"]

實例化AipNlp的代碼:

from aip import AipNlp


APP_ID = "15217709"
API_KEY = "eNiP5QUsgBh6QwpbNv8Qmsy3"
SECRET_KEY = "gwhM3wDo0Kjjd1PDIxqqW4Bfex10Y4f3"

nlp_client = AipNlp(APP_ID, API_KEY, SECRET_KEY)

text1 = "你叫什麽名字"

text2 = "您怎們稱呼"

res = nlp_client.simnet(text1, text2)

# print(res.get("score"))

最終app的代碼:

from flask import Flask,request, render_template, send_file, jsonify
from uuid import uuid4
from baidu_ai import audio2text
from baidu_ai import my_nip
from baidu_ai import text2audio
import os

# 實例化一個Flask的對象
app = Flask(__name__)

# 寫一個路由
@app.route("/", methods=["GET", "POST"])
def index():
    if request.method == "GET":
        return render_template("web.html")


@app.route("/toy_uploader", methods=["GET", "POST"])
def toy_uploader():
    # 拼接路徑
    file_path = os.path.join("audios", f"{uuid4()}.wav")
    #
    request.files["record"].save(file_path)
    # 將音頻變成文本的函數,並的到音頻的內容
    Q = audio2text(file_path)
    print(Q)
    # 調用aipNlp
    A = my_nip(Q)
    # 將圖靈處理後的數據返回的文本
    filename = text2audio(A)
    print(filename)
    # 返回給前端json格式的數據
    return jsonify({"filename": filename, "A": A})


@app.route("/get_audio/<filename>", methods=["GET", "POST"])
def get_audio(filename):
    # 拼接新的路徑
    new_file = os.path.join("audios", filename)
    print("2", new_file)
    # 返回給前端新的文件
    return send_file(new_file)


if __name__ == ‘__main__‘:
    app.run("192.168.12.49", 5000, debug=True)

前端代碼:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<audio src="" controls autoplay id="player"></audio>
<p>
    <button onclick="start_reco()" style="background-color: red">錄制消息</button>
</p>
<p>
    <button onclick="stop_reco()" style="background-color: green">發送消息</button>
</p>
</body>
<script type="text/javascript" src="/static/jquery-3.3.1.min.js"></script>
<script type="text/javascript" src="/static/Recorder.js"></script>
<script type="text/javascript">
    var serv = "http://192.168.12.49:5000";
    // var get_music = "http://192.168.1.102:9527/get_music/";
    // var get_chat = "http://192.168.1.102:9527/get_chat/";
    var reco = null;

    var audio_context = new AudioContext();
    navigator.getUserMedia = (navigator.getUserMedia ||
        navigator.webkitGetUserMedia ||
        navigator.mozGetUserMedia ||
        navigator.msGetUserMedia);

    navigator.getUserMedia({audio: true}, create_stream, function (err) {
        console.log(err)
    });

    function create_stream(user_media) {
        var stream_input = audio_context.createMediaStreamSource(user_media);
        reco = new Recorder(stream_input);
    }

    function start_reco() {
        reco.record();
    }

    function stop_reco() {
        reco.stop();
        get_audio();
        reco.clear();
    }

    function get_audio() {
        reco.exportWAV(function (wav_file) {
            // wav_file = Blob對象 file對象
            // ws.send(wav_file);
            var formdata = new FormData();
            formdata.append("record", wav_file);
            // formdata.append("sender", toy_id);
            // formdata.append("to_user", document.getElementById("from_user").innerText);
            $.ajax({
                url: serv + "/toy_uploader",
                type: ‘post‘,
                processData: false,
                contentType: false,
                data: formdata,
                dataType: ‘json‘,
                success: function (data) {
                    console.log(data.A);
                    // console.log(data);

                    document.getElementById("player").src =
                        "http://192.168.12.49:5000/get_audio/" + data.filename;


                }
            });

        })
    }





</script>
</html>

群聊的代碼:

from flask import Flask, request,render_template
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer

from geventwebsocket.websocket import WebSocket

# 實例化一個app對象
app = Flask(__name__)  # type: Flask
# 準備一個存放連接用戶的容器
user_socket_list = []

@app.route("/ws")
def ws():
    user_socket = request.environ.get("wsgi.websocket")  # type: WebSocket
    if user_socket:
        # 把已經連接的用戶添加到用戶的連接列表中
        user_socket_list.append(user_socket)
    # print(len(user_socket_list), user_socket_list)
    while 1:
        # 獲取到用戶的數據
        msg = user_socket.receive()
        print(msg)
        for usocket in user_socket_list:
            if user_socket == usocket:
                continue
            try:
                usocket.send(msg)
            except:
                continue


@app.route("/")
def index():
    return render_template("ws_group_chat.html")


if __name__ == ‘__main__‘:
    http_serv = WSGIServer(("192.168.12.49",5000), app, handler_class=WebSocketHandler)
    http_serv.serve_forever()

群聊的前端代碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-Type" charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<p>發送內容:<input type="text" id="message"><button onclick="send_msg()">發送消息</button></p>
<div id="msg_list" style="width: 500px;">

</div>
</body>
<script type="application/javascript">
    var ws = new WebSocket("ws://192.168.12.49:5000/ws");
    // ws.onopen = function(){
    //   alert("歡迎來到S14群噴");
    // };
    ws.onmessage = function (ws_status) {
        console.log(ws_status.data);
        var ptag = document.createElement("p");
        ptag.innerText = ws_status.data;
        document.getElementById("msg_list").appendChild(ptag);
    };

    function send_msg() {
        var msg = document.getElementById("message").value;
        var ptag = document.createElement("p");
        ptag.style.cssText = "text-align: right;";
        ptag.innerText = msg;
        document.getElementById("msg_list").appendChild(ptag);
        ws.send(msg);
    }
</script>
</html>

單聊的代碼:

from flask import Flask, request,render_template
from geventwebsocket.handler import WebSocketHandler
from gevent.pywsgi import WSGIServer
import json
from geventwebsocket.websocket import WebSocket

# 實例化一個Flask對象
app = Flask(__name__)  # type:Flask

user_socket_dict = {

}

@app.route("/ws/<user>")
def ws(user):
    # 使用微博socket服務
    user_socket = request.environ.get("wsgi.websocket")  # type:WebSocket
    # 如果存在user_socket連接
    if user_socket:
        # 是該用戶連接socket
        user_socket_dict[user] = user_socket
    print(len(user_socket_dict), user_socket_dict)

    while 1:
        # 接收到連接用戶發過來的信息
        msg = user_socket.receive()
        print(msg)
        # 把收到的msg反序列化
        msg_dict = json.loads(msg)
        # 獲取到反序列化的有效內容
        to_usocket = user_socket_dict.get(msg_dict.get("to_user"))
        # 發送給前端顯示
        to_usocket.send(json.dumps({"from_user": user, "to_user": msg_dict.get("to_user"), "msg": msg_dict.get("msg")}))


@app.route("/")
def index():
    return render_template("ws.html")


if __name__ == ‘__main__‘:
    http_serv = WSGIServer(("192.168.12.49", 5000), app, handler_class=WebSocketHandler)
    http_serv.serve_forever()

單聊的前端代碼:

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta http-equiv="content-Type" charset="UTF-8">
    <meta http-equiv="x-ua-compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Title</title>
</head>
<body>
<p>您的昵稱:<input type="text" id="nick"><button onclick="openws()">進入聊天室</button></p>
<p>給<input type="text" id="to_user">發送:<input type="text" id="message"><button onclick="send_msg()">發送消息</button></p>
<div id="msg_list" style="width: 500px;">

</div>
</body>
<script type="application/javascript">
    var ws = null;
    // ws.onopen = function(){
    //   alert("歡迎來到S14群噴");
    // };

    function openws(){
        var nick = document.getElementById("nick").value;
        ws = new WebSocket("ws://192.168.12.49:5000/ws/"+nick);
        ws.onmessage = function (ws_status) {
            console.log(ws_status.data);
            var msg_obj = JSON.parse(ws_status.data);
            var ptag = document.createElement("p");
            ptag.innerText = msg_obj.from_user + " : " +msg_obj.msg;
            document.getElementById("msg_list").appendChild(ptag);
        };
    }

    function send_msg() {
        var msg = document.getElementById("message").value;
        var from_user = document.getElementById("nick").value;
        var to_user = document.getElementById("to_user").value;
        var ptag = document.createElement("p");
        ptag.style.cssText = "text-align: right;";
        ptag.innerText = msg + " : "+ from_user;
        document.getElementById("msg_list").appendChild(ptag);
        var msg_obj = {
            msg:msg,
            from_user:from_user,
            to_user:to_user
        };
        ws.send(JSON.stringify(msg_obj));
    };

</script>
</html>

Websocket代碼:

解密代碼:

 1 # b‘\x81\x83\xceH\xb6\x85\xffz\x85‘
 2 
 3 hashstr = b‘\x81\x83\xceH\xb6\x85\xffz\x85‘
 4 # b‘\x81    \x83    \xceH\xb6\x85\xffz\x85‘
 5 
 6 # 將第二個字節也就是 \x83 第9-16位 進行與127進行位運算
 7 payload = hashstr[1] & 127
 8 print(payload)
 9 if payload == 127:
10     extend_payload_len = hashstr[2:10]
11     mask = hashstr[10:14]
12     decoded = hashstr[14:]
13 # 當位運算結果等於127時,則第3-10個字節為數據長度
14 # 第11-14字節為mask 解密所需字符串
15 # 則數據為第15字節至結尾
16 
17 if payload == 126:
18     extend_payload_len = hashstr[2:4]
19     mask = hashstr[4:8]
20     decoded = hashstr[8:]
21 # 當位運算結果等於126時,則第3-4個字節為數據長度
22 # 第5-8字節為mask 解密所需字符串
23 # 則數據為第9字節至結尾
24 
25 
26 if payload <= 125:
27     extend_payload_len = None
28     mask = hashstr[2:6]
29     decoded = hashstr[6:]
30 
31 # 當位運算結果小於等於125時,則這個數字就是數據的長度
32 # 第3-6字節為mask 解密所需字符串
33 # 則數據為第7字節至結尾
34 
35 str_byte = bytearray()
36 
37 for i in range(len(decoded)):
38     byte = decoded[i] ^ mask[i % 4]
39     str_byte.append(byte)
40 
41 print(str_byte.decode("utf8"))

加密:

 1 import struct
 2 msg_bytes = "hello".encode("utf8")
 3 token = b"\x81"
 4 length = len(msg_bytes)
 5 
 6 if length < 126:
 7     token += struct.pack("B", length)
 8 elif length == 126:
 9     token += struct.pack("!BH", 126, length)
10 else:
11     token += struct.pack("!BQ", 127, length)
12 
13 msg = token + msg_bytes
14 
15 print(msg)

基於websocket的單聊.群聊