中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

網(wǎng)站編輯專題怎么做東莞百度seo推廣公司

網(wǎng)站編輯專題怎么做,東莞百度seo推廣公司,長(zhǎng)沙景點(diǎn)分布圖,免費(fèi)的網(wǎng)站app哪個(gè)靠譜實(shí)現(xiàn)功能主要思路:在網(wǎng)頁(yè)端進(jìn)行語(yǔ)音輸入,PC機(jī)可以實(shí)時(shí)接收并播放語(yǔ)音流。 此時(shí),Qt程序做客戶端,Web端做服務(wù)器,使用QWebSocket進(jìn)行通訊,實(shí)時(shí)播放接收的語(yǔ)音流。 功能實(shí)現(xiàn) 想要實(shí)現(xiàn)該功能,需要…

實(shí)現(xiàn)功能主要思路:在網(wǎng)頁(yè)端進(jìn)行語(yǔ)音輸入,PC機(jī)可以實(shí)時(shí)接收并播放語(yǔ)音流。

此時(shí),Qt程序做客戶端,Web端做服務(wù)器,使用QWebSocket進(jìn)行通訊,實(shí)時(shí)播放接收的語(yǔ)音流。

功能實(shí)現(xiàn)

想要實(shí)現(xiàn)該功能,需要完成以下兩大部分。

第一部分:QWebSocket通訊實(shí)現(xiàn)。(簡(jiǎn)單

第二部分:語(yǔ)音流實(shí)時(shí)播放功能。(稍微有點(diǎn)難度

接下來(lái)對(duì)于該功能實(shí)現(xiàn)進(jìn)行具體的講解。

1:建立通訊

1.1:創(chuàng)建QWebSocket通訊

添加頭文件

#include <QWebSocketServer>
#include <QWebSocket>

聲明WebSocket對(duì)象并響應(yīng)消息

m_pWebClient = new QWebSocket;
connect(m_pWebClient, &QWebSocket::connected, this, &QWebSocketManager::MsgRecievd_Server_Connected);
connect(m_pWebClient, &QWebSocket::disconnected, this, &QWebSocketManager::MsgRecievd_Server_Disconnected);
connect(m_pWebClient, &QWebSocket::textMessageReceived, this, &QWebSocketManager::MsgRecievd_Server_TextMessageReceived);
connect(m_pWebClient, &QWebSocket::binaryMessageReceived, this, &QWebSocketManager::MsgRecievd_Server_BinaryMessageReceived);

分別響應(yīng)了:連接、斷開(kāi)、接收字符串內(nèi)容、接收二進(jìn)制內(nèi)容。

1.2:建立心跳包

一說(shuō)到通訊,首先想到的應(yīng)該是心跳包機(jī)制。在與Web通訊也是如此,為了防止掉線,程序中也需要設(shè)定一個(gè)心跳包機(jī)制。

為了保證心跳包有連接,但不頻繁發(fā)送,可以采用在無(wú)數(shù)據(jù)發(fā)送時(shí),采用3秒~10秒之間發(fā)送一條。

使用方法:QTimer進(jìn)行心跳包發(fā)送。

在程序使用過(guò)程中,不需要精確發(fā)送時(shí)間,只要在指定時(shí)間范圍內(nèi)(3s~10s)發(fā)送就可以了。

定義時(shí)間更新變量

DWORD m_dwReciveTime;//接收到WebSocket消息的時(shí)間

每次接收到web服務(wù)端發(fā)送數(shù)據(jù)時(shí),實(shí)時(shí)更新接收時(shí)間。

void QWebSocketManager::MsgRecievd_Server_TextMessageReceived(const QString &message)
{qDebug() << QStringLiteral("接收內(nèi)容:") << message;m_dwReciveTime = GetTickCount(); //更新接收時(shí)間
}
void QWebSocketManager::MsgRecievd_Server_BinaryMessageReceived(const QByteArray &message)
{qDebug() << QStringLiteral("接收內(nèi)容:") << message;m_dwReciveTime = GetTickCount(); //更新接收時(shí)間
}

在項(xiàng)目中重寫了兩個(gè)接收消息,所以都需要實(shí)時(shí)更新接收時(shí)間。

此時(shí)需要開(kāi)啟定時(shí)器,假設(shè)每間隔3秒訪問(wèn)一次,定時(shí)器核心代碼,如下:

DWORD dwCalc = GetTickCount() - pThis->m_dwReciveTime; //時(shí)間差 = 最新時(shí)間 - 模擬人上傳數(shù)據(jù)時(shí)間
if (dwCalc < g_nWebSocektHeartTime)
{//時(shí)間差 < 最小心跳包
}
else if ((dwCalc > g_nWebSocektHeartTime) && (dwCalc < g_nWebSocketLostConnectTime))
{//發(fā)送心跳包協(xié)議
}
else if(dwCalc > g_nWebSocketLostConnectTime)
{qDebug() << QStringLiteral("連接超時(shí)!");
}

注意:這是我在通訊過(guò)程中進(jìn)行了一點(diǎn)點(diǎn)小小優(yōu)化,大家也可以采用喲~

每次觸發(fā)定時(shí)器時(shí),并沒(méi)有直接發(fā)送心跳包,而是當(dāng)間隔超過(guò)10秒后代表斷開(kāi)連接了。

1.3:接收web端音頻流

在1.1中實(shí)現(xiàn)了QWebSocket的兩個(gè)消息數(shù)據(jù)接收:textMessageReceived、binaryMessageReceived

具體使用哪個(gè)消息,需要對(duì)應(yīng)服務(wù)端是如何發(fā)送的,一般而言,音頻流采用二進(jìn)制流的方式比較安全。

接收語(yǔ)音流數(shù)據(jù),實(shí)例代碼如下:

void QWebSocketManager::MsgRecievd_Server_BinaryMessageReceived(const QByteArray &message)
{//qDebug() << QStringLiteral("MsgRecievd_Server_BinaryMessageReceived,內(nèi)容:") << message;
}

接收到音頻流以后,該如何進(jìn)行播放呢?

接下來(lái)就需要進(jìn)行第二步重要功能:語(yǔ)音流實(shí)時(shí)播放功能

2:語(yǔ)音流實(shí)時(shí)播放功能

在這里我用的是:QAudioOutput類,使用該類方便操作。

2.1:初始化輸出音頻參數(shù)

QAudioFormat audio_out_format; 
//設(shè)置錄音的格式
audio_out_format.setSampleRate(8000); //采樣率
audio_out_format.setChannelCount(1); //通道數(shù)
audio_out_format.setSampleSize(16);
audio_out_format.setCodec("audio/pcm"); //編碼格式
audio_out_format.setByteOrder(QAudioFormat::LittleEndian); //樣本是小端字節(jié)順序
audio_out_format.setSampleType(QAudioFormat::SignedInt); //樣本類型QAudioDeviceInfo  info(QAudioDeviceInfo::defaultOutputDevice());m_pAudioOutput = new QAudioOutput(audio_out_format);
m_pStreamOutput = m_pAudioOutput->start();
m_nPeriodSize = m_pAudioOutput->periodSize();

代碼分析:

錄音的格式要與服務(wù)端輸入的音頻流格式才能保證客戶端接收到清晰完整的音頻流。

此時(shí),需要注意的是最后一行代碼:m_nPeriodSize = m_pAudioOutput->periodSize();

這是實(shí)現(xiàn)播放音頻流的核心之一!

2.2:播放接收的音頻流

針對(duì)這部分實(shí)現(xiàn)方式,我經(jīng)歷了以下幾個(gè)步驟,已踩坑,希望對(duì)大家有用!

簡(jiǎn)單有問(wèn)題的實(shí)現(xiàn)方式
void QWebSocketManager::MsgRecievd_Server_BinaryMessageReceived(const QByteArray &message)
{//qDebug() << QStringLiteral("MsgRecievd_Server_BinaryMessageReceived,內(nèi)容:") << message;m_dwReciveTime = GetTickCount(); //更新接收時(shí)間m_pStreamOutput->write(array); //播放音頻流
}

接收到音頻流就直接播放。使用這種方法會(huì)發(fā)現(xiàn),音頻是可以播放,但是嘰里呱啦的,每次智能聽(tīng)到說(shuō)話的第一個(gè)字,其余的全都聽(tīng)不到了。

此時(shí),你會(huì)懷疑是不是服務(wù)端傳入的音頻流不正確呢?因?yàn)榭蛻舳丝梢圆シ怕曇?。如果你沿著這條路走,那你就錯(cuò)了。

原因:之所以只能聽(tīng)到說(shuō)話的第一個(gè)字是因?yàn)?#xff0c;頻繁地接收數(shù)據(jù),上一次接收的音頻流還未播放完畢就立刻播放下一條音頻流,所以會(huì)出現(xiàn)這種問(wèn)題了。

那么,該如何解決這種問(wèn)題呢?

在這里就用到了初始化時(shí)我所說(shuō)的核心代碼了。

m_nPeriodSize 是每次播放一條完整音頻格式的大小,服務(wù)端傳入的數(shù)據(jù)大小我們無(wú)法控制,但是可以在播放時(shí),每次取m_nPeriodSize 大小的數(shù)據(jù)進(jìn)行播放,就能保證數(shù)據(jù)的完整性。

那么,如何知道上一次播放的音頻流已經(jīng)完成了呢?

使用m_pAudioOutput->bytesFree(),循環(huán)進(jìn)行判斷,只有當(dāng)釋放的緩存數(shù)小于m_nPeriodSize 才能夠繼續(xù)播放音頻流

下面為大家展示有效地實(shí)現(xiàn)方法。

復(fù)雜有效的實(shí)現(xiàn)方式
void QWebSocketManager::MsgRecievd_Server_BinaryMessageReceived(const QByteArray &message)
{//qDebug() << QStringLiteral("MsgRecievd_Server_BinaryMessageReceived,內(nèi)容:") << message;m_dwReciveTime = GetTickCount(); //更新接收時(shí)間{std::lock_guard<std::mutex> lck(m_mutexPcm);  //C11用法m_ArrayAudio.append(message);}if (m_bRunningAudio == false){m_bRunningAudio = true; //開(kāi)啟數(shù)據(jù)處理線程m_threadAudio = std::thread(&QWebSocketManager::ThreadProcessingPCMData, this, this);}
}

代碼解析:

當(dāng)接收到第一條音頻數(shù)據(jù)時(shí),開(kāi)啟線程,將音頻播放處理放到線程中進(jìn)行判斷,只有把上一次播放的音頻緩存釋放完成后,才能夠從緩存m_ArrayAudio中獲取m_nPeriodSize大小的數(shù)據(jù)

線程實(shí)現(xiàn)代碼,如下:

unsigned int QWebSocketManager::ThreadProcessingPCMData(void* pParam)
{QWebSocketManager* pThis = reinterpret_cast<QWebSocketManager*>(pParam);while (pThis->m_bRunningAudio == true){//只有滿足一個(gè)完整包數(shù)據(jù)時(shí),才需要處理if (pThis->m_ArrayAudio.count() >= m_nPeriodSize){if (m_pAudioOutput->bytesFree() < m_nPeriodSize){Sleep(5);continue; //當(dāng)前音頻釋放大小 < 固定大小時(shí),不處理}std::lock_guard<std::mutex> lck(m_mutexPcm);  //C11用法QByteArray array = pThis->m_ArrayAudio.mid(0, m_nPeriodSize);pThis->m_pStreamOutput->write(array);pThis->m_ArrayAudio.remove(0, m_nPeriodSize);qDebug() << QStringLiteral("處理一次完整的音頻,此時(shí)剩余大小 = ") << pThis->m_ArrayAudio.count();}else{Sleep(1000);}}return 0;
}

以上就是核心的實(shí)現(xiàn)流程了,如果需要查看原始代碼的,請(qǐng)看下面鏈接

Qt中使用QWebSocket與Web進(jìn)行通訊,實(shí)時(shí)語(yǔ)音通話

我是糯諾諾米團(tuán),一名C++開(kāi)發(fā)程序媛~

http://www.risenshineclean.com/news/49246.html

相關(guān)文章:

  • 網(wǎng)站建設(shè)公司該如何選擇谷歌搜索引擎香港免費(fèi)入口
  • 網(wǎng)站團(tuán)購(gòu)報(bào)名怎么做整站seo排名外包
  • wordpress 前臺(tái)注冊(cè)seo排名優(yōu)化哪家好
  • 機(jī)票特價(jià)網(wǎng)站建設(shè)seo咨詢解決方案
  • 增城微網(wǎng)站建設(shè)企業(yè)營(yíng)銷模式
  • 互聯(lián)網(wǎng)運(yùn)營(yíng)網(wǎng)站免費(fèi)網(wǎng)絡(luò)推廣網(wǎng)址
  • 一家專門做開(kāi)網(wǎng)店的網(wǎng)站西安百度seo代理
  • 怎么建立自己的站點(diǎn)上海網(wǎng)站建設(shè)開(kāi)發(fā)
  • 上海推廣網(wǎng)站長(zhǎng)沙網(wǎng)絡(luò)推廣公司
  • 北京做網(wǎng)站公司有哪些百度搜索官網(wǎng)
  • 特價(jià)網(wǎng)站建設(shè)官網(wǎng)阿里云域名注冊(cè)入口
  • 好搜客網(wǎng)站如何推廣app
  • 安徽區(qū)塊鏈虛擬幣網(wǎng)站開(kāi)發(fā)方案濟(jì)南網(wǎng)站自然優(yōu)化
  • 無(wú)錫高端網(wǎng)站設(shè)計(jì)建設(shè)seo優(yōu)化軟件大全
  • 怎么做網(wǎng)站旅游宣傳第三波疫情將全面大爆發(fā)
  • 東莞公司網(wǎng)站建設(shè)seo推廣需要多少錢
  • 安溪縣住房和城鄉(xiāng)規(guī)劃建設(shè)網(wǎng)站銷售平臺(tái)排名
  • 門戶網(wǎng)站標(biāo)題居中加大百度搜索 手機(jī)
  • 教做黏土手工的網(wǎng)站企業(yè)網(wǎng)絡(luò)推廣計(jì)劃
  • 鄭州網(wǎng)站推廣外包地址品牌營(yíng)銷策略分析論文
  • 做關(guān)于家鄉(xiāng)的網(wǎng)站國(guó)內(nèi)搜索引擎大全
  • 做企業(yè)網(wǎng)站推廣多少錢ciliba磁力搜索引擎
  • 南京企業(yè)網(wǎng)站建設(shè)網(wǎng)絡(luò)推廣優(yōu)化網(wǎng)站
  • 中國(guó)循環(huán)經(jīng)濟(jì)網(wǎng)站開(kāi)發(fā)與設(shè)計(jì)傳媒公司
  • 網(wǎng)站模板庫(kù)軟件系統(tǒng)優(yōu)化是什么意思
  • 專業(yè)做淘寶網(wǎng)站紹興小廣告網(wǎng)站
  • java web網(wǎng)站建設(shè)關(guān)鍵詞優(yōu)化分析工具
  • 網(wǎng)站地圖怎么做XMLaso優(yōu)化前景
  • 山東聊城建設(shè)學(xué)校官網(wǎng)企業(yè)seo關(guān)鍵字優(yōu)化
  • 站長(zhǎng)工具seo下載推客平臺(tái)