本项目主要通过tcp实现的并发聊天室再加上百度ai的语音识别接口,实现的支持语音识别输入的并发聊天室。
1.服务器
服务器设置的一个没有ui的界面的软件,实现聊天数据的中介
2.客户端
客户端通过qt写了相应的ui,并加入了语音识别的功能
客户端上的按钮通过相应的槽函数,分别控制着不同的功能
name后的lineEdit-> 进入聊天室使用的昵称
connect -> 连接入聊天室,连接成功后connect变化为disconnect,点击即断开连接
中间的Text Browser ->信息交互界面
Text Browser下的Line Edit ->输入需要发送的消息支持手动输入和语音转化输入
pushbutton->按住说话,按下后进行录音,松开进行识别并将识别结果放入上边的LineEdit
pushbutton->发送,按下按钮将信息发送至聊天室
pushbutton->清楚,如果写入信息有误或者不想发送,按下可清空信息框内信息
3. 运行结果
4.代码
1.tcpserver.cpp
#include "Server.h"
Server::Server(QObject *parent) : QObject(parent)
{
}
void Server::startServer()
{
allClients = new QVector<QTcpSocket*>;
chatServer = new QTcpServer();
// 限制同时最大连接数为10
chatServer->setMaxPendingConnections(10);
connect(chatServer, SIGNAL(newConnection()), this, SLOT(newClientConnection()));
// 监听端口8081
if (chatServer->listen(QHostAddress::Any, 8001))
{
qDebug() << "Server has started. Listening to port 8001.";
}
else
{
qDebug() << "Server failed to start. Error: " + chatServer->errorString();
}
}
void Server::sendMessageToClients(QString message)
{
if (allClients->size() > 0)
{
for (int i = 0; i < allClients->size(); i++)
{
if (allClients->at(i)->isOpen() && allClients->at(i)->isWritable())
{
allClients->at(i)->write(message.toUtf8());
}
}
}
}
void Server::newClientConnection()
{
QTcpSocket* client = chatServer->nextPendingConnection();
QString ipAddress = client->peerAddress().toString();
int port = client->peerPort();
connect(client, &QTcpSocket::disconnected, this, &Server::socketDisconnected);
connect(client, &QTcpSocket::readyRead, this, &Server::socketReadyRead);
connect(client, &QTcpSocket::stateChanged, this, &Server::socketStateChanged);
allClients->push_back(client);
qDebug() << "Socket connected from " + ipAddress + ":" + QString::number(port);
}
void Server::socketDisconnected()
{
QTcpSocket* client = qobject_cast<QTcpSocket*>(QObject::sender());
QString socketIpAddress = client->peerAddress().toString();
int port = client->peerPort();
qDebug() << "Socket disconnected from " + socketIpAddress + ":" + QString::number(port);
}
void Server::socketReadyRead()
{
QTcpSocket* client = qobject_cast<QTcpSocket*>(QObject::sender());
QString socketIpAddress = client->peerAddress().toString();
int port = client->peerPort();
QString data = QString(client->readAll());
qDebug() << "Message: " + data + " (" + socketIpAddress + ":" + QString::number(port) + ")";
sendMessageToClients(data);
}
void Server::socketStateChanged(QAbstractSocket::SocketState state)
{
QTcpSocket* client = qobject_cast<QTcpSocket*>(QObject::sender());
QString socketIpAddress = client->peerAddress().toString();
int port = client->peerPort();
QString desc;
if (state == QAbstractSocket::UnconnectedState)
desc = "The socket is not connected.";
else if (state == QAbstractSocket::HostLookupState)
desc = "The socket is performing a host name lookup.";
else if (state == QAbstractSocket::ConnectingState)
desc = "The socket has started establishing a connection.";
else if (state == QAbstractSocket::ConnectedState)
desc = "A connection is established.";
else if (state == QAbstractSocket::BoundState)
desc = "The socket is bound to an address and port.";
else if (state == QAbstractSocket::ClosingState)
desc = "The socket is about to close (data may still be waiting to be written).";
else if (state == QAbstractSocket::ListeningState)
desc = "For internal use only.";
qDebug() << "Socket state changed (" + socketIpAddress + ":" + QString::number(port) + "): " + desc;
}
tcpclient:
语音识别处理:
#include "speech.h"
QString accessToken;
speech::speech(QObject *parent) : QObject(parent)
{
}
QString speech::speechIdentify(QString fileName)
{
// 获取access_token;
//QNetworkRequest request(QUrl(QString("http://openapi.baidu.com/oauth/2.0/token?")));
QString tokenUrl = "http://openapi.baidu.com/oauth/2.0/token?";
// qDebug() << tokenUrl;
QMap<QString, QString> header;
header.insert(QString("content-Type"), QString("audio/pcm;rate=16000"));
QByteArray requestData = QString("grant_type=client_credentials&client_id=%1&client_secret=%2&").arg(client_id).arg(client_secret).toLatin1();//发送的内容
QByteArray replyData;
Http m_http;
bool result = m_http.post_sync(tokenUrl, header,requestData, replyData);
if(result){
QString key = "access_token";
accessToken = getJsonValue(replyData, key);
//qDebug() << "11111111111";
}
else{
qDebug() << "access failed!!!!";
}
//识别语音
QString speechUrl = QString(baiduspeechUrl).arg(QHostInfo::localHostName()).arg(accessToken);
QFile file;
requestData.clear();
file.setFileName(fileName);
file.open(QIODevice::ReadOnly);
requestData = file.readAll();
file.close();
//再次发起请求
replyData.clear();
result = m_http.post_sync(speechUrl, header, requestData, replyData);
if(result){
QString key = "result";
QString text = getJsonValue(replyData, key);
return text;
}
else{
QMessageBox::warning(NULL, "识别提示","识别失败");
return "";
}
}
QString speech::getJsonValue(QByteArray ba, QString key)
{
QJsonParseError parseError;
QJsonDocument jsonDocument = QJsonDocument::fromJson(ba, &parseError);
if(jsonDocument.isObject()){
if(jsonDocument.isObject()){
//jsonDocument 转换成json对象
QJsonObject jsonObj = jsonDocument.object();
if(jsonObj.contains(key)){
QJsonValue jsonVal = jsonObj.value(key);
if(jsonVal.isString()){
return jsonVal.toString();
}
else if(jsonVal.isArray()){//数组
QJsonArray arr = jsonVal.toArray();//数组
QJsonValue jv = arr.at(0);
return jv.toString();
}
}
}
}
return "";
}
client主体:
#include "widget.h"
#include "ui_widget.h"
#include "http.h"
#include <QObject>
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
ui->pushButton->setText("按住说话");
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_pushButton_pressed()
{
ui->pushButton->setText("松开识别");
audio = new Audio;
audio->startAudio("1.pcm");//
}
void Widget::on_pushButton_released()
{
// 停止录音
audio->stopAudio();
// 修改按钮文字
ui->pushButton->setText("开始识别");
// 开始识别
speech m_speech;
QString text = m_speech.speechIdentify("1.pcm");
ui->lineEdit->setText(text);
ui->pushButton->setText("按住说话");
}
void Widget::on_pushButton_2_clicked()
{
ui->lineEdit->clear();
}
void Widget::on_connectButton_clicked()
{
if (!connectedToHost)
{
// create a QTcpSocket object called socket and make it connect to a host at 127.0.0.1 on port 8801.
socket = new QTcpSocket();
connect(socket, SIGNAL(connected()), this, SLOT(socketConnected()));
connect(socket, SIGNAL(disconnected()), this, SLOT(socketDisconnected()));
connect(socket, SIGNAL(readyRead()), this, SLOT(socketReadyRead()));
socket->connectToHost("127.0.0.1", 8001);
}
else
{
QString name = ui->nameInput->text();
socket->write("<font color=\"Orange\">" + name.toUtf8() + " has left the chat room.</font>");
socket->disconnectFromHost();
}
}
void Widget::socketConnected()
{
qDebug() << "Connected to server.";
printMessage("<font color=\"Green\">Connected to server.</font>");
QString name = ui->nameInput->text();
socket->write("<font color=\"Purple\">" + name.toUtf8() + " has joined the chat room.</font>");
ui->connectButton->setText("Disconnect");
connectedToHost = true;
}
void Widget::socketDisconnected()
{
qDebug() << "Disconnected from server.";
printMessage("<font color=\"Red\">Disconnected from server.</font>");
ui->connectButton->setText("Connect");
connectedToHost = false;
}
void Widget::socketReadyRead()
{
ui->chatDisplay->append(socket->readAll());
}
void Widget::printMessage(QString message)
{
ui->chatDisplay->append(message);
}
void Widget::on_sendButton_clicked()
{
QString name = ui->nameInput->text();
QString message = ui->lineEdit->text();
socket->write("<font color=\"Blue\">" + name.toUtf8() + "</font>: " + message.toUtf8());
ui->lineEdit->clear();
}
相关源码:
聊天室1.0 · mihuiyu-YunYang/通过QT_TCP和百度AI接口实现的支持语音输入的多人聊天室 - 码云 - 开源中国 (gitee.com)
注:该项目仅做学习使用,如有侵权联系删除,
邮箱2217258154@qq.com