WebRTC(Web Real-Time Communication,網(wǎng)頁即時通信),是一個支持網(wǎng)頁瀏覽器進行實時語音對話或視頻對話的技術,目的是無插件實現(xiàn)web端的實時通信的能力。WebRTC提供了視頻會議的核心技術,包括音視頻的采集、編解碼、網(wǎng)絡傳輸、展示等功能,并且還支持跨平臺,包括linux、windows、mac、android等。
WebRTC
2010 年 Google 以 6820 萬美元收購 VoIP 軟件開發(fā)商 Global IP Solutions 的 GIPS 引擎,在經(jīng)過收購之后沒多久,Google 將該引擎改名為“WebRTC”,并宣布向開發(fā)者們開源了源代碼。
2012 年,Google 將 WebRTC 集成到 Chrome 瀏覽器中。隨后, Mozilla、Opera、Ericsson 等 PC 瀏覽器以及手機瀏覽器均開始支持 WebRTC 技術。
2017 年,蘋果在 WWDC17 上正式宣布其瀏覽器內(nèi)核 WebKit 也正式支持 WebRTC。
基于 Chromium 的新版 Edge 現(xiàn)在可在預覽版中使用。新版本的 Edge 提供了 WebRTC 開發(fā)者常用的許多功能,如支持數(shù)據(jù)通道、RTCPeerConnection 中的 Strem、VP9 編解碼器和 MediaStream Recording。
在 Discord、Google Hangouts 和 Facebook Messenger 等一些國內(nèi)的多媒體網(wǎng)絡應用中,也都需要 WebRTC 才能實現(xiàn)。
但是,WebRTC 的發(fā)展還面臨著諸多的挑戰(zhàn):
瀏覽器面臨的主要挑戰(zhàn)是完成 WebRTC 1.0 API 的實現(xiàn),以及消除實現(xiàn)差異。WebRTC API 在其歷史中經(jīng)歷了三次主要迭代,需要實現(xiàn)互操作性、改進測試覆蓋率等方面的標準。W3C 在實現(xiàn)這一目標方面一直在穩(wěn)步前進,但還未成熟。
前實時音視頻通信領域,也并不只有 WebRTC 一種可供選擇的技術,專有的自研協(xié)議和 WebRTC 的互操作性通常使用網(wǎng)關實現(xiàn)。
WebRTC協(xié)議介紹:https://www.cnblogs.com/SingleCat/p/11315349.html
基于Webrtc、Kurento的一種低延遲架構(gòu)實現(xiàn):https://www.jianshu.com/p/ac307371def4
WebRTC的開源實現(xiàn):
1、Jitsi Videobridge
Jitsi是一個SFU開源框架,由Atlassian維護,被集成到HipChat中。
Jitsi是一個處理XMPP信號流的SFU,適用于SIP/XMPP視頻通話,會議,聊天,桌面共享,文件傳輸。如果你不需要SFU或者使用其他信號協(xié)議,最好還是使用其他項目。但由于Jitsi項目的簡單明了,很多外包供應商很喜歡使用Jitsi,將它集成到自己的項目案例當中。
Github項目地址:https://github.com/jitsi/jitsi
2、Kurento
Kurento 是一個 WebRTC 流媒體服務器以及一些客戶端API,可以實現(xiàn)webrtc mcu、sfu等功能。2016年被Twilio收購,Kurento目前推進到6.13版本。nubomedia 開源框架是基于kurento開發(fā)的官方paas 平臺,提高了穩(wěn)定性,但是并不推薦學習使用。它可以實現(xiàn)的功能包括
Kurento服務器實現(xiàn)的功能
官網(wǎng)地址:http://www.kurento.org
2019年12月發(fā)布的最新的6.13版本的文檔:https://doc-kurento.readthedocs.io/en/6.13.0/project/relnotes/v6_13_0.html
由于Kurento開源服務只有Ubuntu的版本,所以在WSL的UBUNTU上安裝Kurento服務器是再適合不過了。建議安裝Kurento的6.11版本,因為最新的版本并不支持kms-datachannelexample等組件,無法運行顯示字幕等實例,如果只是學習WebRTC,可以無視。
6.11版本的文檔https://doc-kurento.readthedocs.io/en/6.11.0/user/about.html
WSL上的安裝:
1、 在Ubuntu子系統(tǒng)內(nèi)確認安裝GnuPG
sudo apt-get update && sudo apt-get install --no-install-recommends --yes \
gnupg
在Ubuntu子系統(tǒng)內(nèi)確認安裝GnuPG
2、 在16.04的Ubuntu子系統(tǒng),執(zhí)行:
DISTRO="xenial" # KMS for Ubuntu 16.04 (Xenial)
DISTRO="bionic" # KMS for Ubuntu 18.04 (Bionic)
在18.04的Ubuntu子系統(tǒng),執(zhí)行
DISTRO="bionic" # KMS for Ubuntu 18.04 (Bionic)
3、下面兩條指令指令增加Kurento倉庫到系統(tǒng)配置中:
sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 5AFA7A83
sudo tee "/etc/apt/sources.list.d/kurento.list" >/dev/null <<EOF
# Kurento Media Server - Release packages
deb [arch=amd64] http://ubuntu.openvidu.io/6.13.0 $DISTRO kms6
EOF
增加Kurento倉庫到系統(tǒng)配置
4、 安裝Kurento服務KMS
sudo apt-get update && sudo apt-get install --yes kurento-media-server
安裝過程中下載較慢,特別是下載GStream組件的時候,如果下載速度降到很低,可以中斷重新下載,具備斷點重傳。
5、安裝完成后,可以用下面的指令啟動服務,或者停止服務
sudo service kurento-media-server start
sudo service kurento-media-server stop
啟動KMS服務
KMS會在Ubuntu子系統(tǒng)本地生成一個端口在8888的服務,可以通過/etc/kurento/kurento.conf.json進行KMS的詳細配置。
KMS服務的配置
6、可以在/var/log /kurento-media-server/下查看KMS的日志信息
KMS的日志信息
7、如果需要在遠程服務器上部署KMS服務,則需要繼續(xù)安裝STUN或者TURN服務器,來穿透NAT墻。可以參照該網(wǎng)文來安裝Docker設置,https://blog.csdn.net/XRRRICK/article/details/85010829
8、之后可以繼續(xù)下載Kurento的示例代碼來安裝運行,有SpringBoot、NodeJS等版本的程序供選擇。我這里用SpringBoot就是Java的例程:Kurento Java Tutorial - Hello World
(1) 運行以下命令來下載Java實例代碼、設置6.11分支,打包運行SpringBoot項目:
git clone https://github.com/Kurento/kurento-tutorial-java.git
cd kurento-tutorial-java/kurento-hello-world
git checkout 6.11.0
mvn -U clean spring-boot:run -Dkms.url=ws://localhost:8888/kurento
啟動Hello World的SpringBoot項目
這里的-Dkms.url=ws://localhost:8888/kurento是本地KMS服務提供的路徑,如果端口沒有什么變化,可以省略不寫。
(2) 如果啟動沒有什么錯誤的話,就可以在WebRTC兼容的瀏覽器(Chrome、Edge、360瀏覽器等)輸入以下地址(注意是https協(xié)議):https://localhost:8443/,這個Helloworld實例是將本地攝像頭采集到的音視頻流發(fā)送到KMS服務器后,又回送到瀏覽器,左邊的Video組件是顯示本地的視頻,右邊的Video組件是顯示回送的視頻。
可以看到界面:
Helloworld示例
在界面的console里你可以看到整個瀏覽器客戶端與應用服務器(SpringBoot創(chuàng)建的8433端口的Web服務)的消息協(xié)商過程。
如果在Chrome瀏覽器中,可以在瀏覽器的另一個標簽里打開:chrome://webrtc-internals/,可以看到Google瀏覽器提供的對WebRTC數(shù)據(jù)的統(tǒng)計。
Chrome瀏覽器里的WebRTC統(tǒng)計信息
有興趣的同學可以摘取其中的靜態(tài)JS文件和庫文件,組合到自己的應用里。
可以在我的網(wǎng)站rtc目錄下訪問這個helloworld示例,rtc/hello.html
PyQt5中,可以使用PyQtWebEngine模塊快速定制專屬瀏覽器,缺省的PyQt5包中并不包含這個模塊,請使用命令:
pip install PyQtWebEngine
安裝這個模塊。
QWebEngineView類提供了一個用于查看和編輯Web文檔部件,web view是Qt WebEngine網(wǎng)頁瀏覽模塊的主要部件的組件。可以在各種應用程序中使用它來實時顯示Internet上的Web內(nèi)容。
和其他Qt部件一樣,必須show()函數(shù)才可以顯示W(wǎng)eb視圖,簡單的示例代碼如下:
webView = QWebEegineView(self)
view.load(QUrl('http://qt-project.org/'))
view.show()
QWebEegineView 常用函數(shù):
QWebEegineView 常用信號:
代碼演示如何定制一個簡單的瀏覽器,備注(QWebEngine 模塊的內(nèi)核使用的Chorme, 測試程序在win10下運行正常,在Ubutun下需要加開關 --no-sandbox)。完整代碼如下:
資源文件:resource.qrc
<RCC>
<qresource>
<file>images/back.png</file>
<file>images/next.png</file>
<file>images/close.png</file>
<file>images/reload.png</file>
</qresource>
</RCC>
代碼文件:
import sys
from PyQt5.QtCore import Qt, QUrl, QSize
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLineEdit,
QMenuBar, QToolBar, QMenu, QAction)
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings
import resource_rc
default_url = 'https://www.toutiao.com/i6856673250190033415/'
class WebEngineView(QWebEngineView):
windowList = []
class DemoBrowser(QMainWindow):
def __init__(self, parent=None):
super(DemoBrowser, self).__init__(parent)
# 設置窗口標題
self.setWindowTitle('實戰(zhàn)Qt for Python: QWeEngineView演示')
# 設置窗口大小
self.resize(640, 480)
webSettings = QWebEngineSettings.globalSettings()
webSettings.setAttribute(QWebEngineSettings.JavascriptEnabled, True)
webSettings.setAttribute(QWebEngineSettings.PluginsEnabled, True)
webSettings.setAttribute(QWebEngineSettings.JavascriptCanOpenWindows, True)
self.browser = QWebEngineView(self)
self.setCentralWidget(self.browser)
self.initBar()
self.browser.load(QUrl(default_url))
def initBar(self):
#菜單條
menuBar = self.menuBar()
menuFile = menuBar.addMenu('文件(&F)')
actionExit = QAction('退出(&X)', self)
actionExit.triggered.connect(QApplication.instance().quit)
menuFile.addAction(actionExit)
#瀏覽器工具條
navBar = QToolBar('Navigation')
navBar.setIconSize(QSize(16, 16))
self.addToolBar(navBar)
self.editUrl = QLineEdit()
#地址欄能響應回車按鍵信號
self.editUrl.returnPressed.connect(self.navigateToUrl)
navBar.addAction(QAction(QIcon(':/images/back.png'), 'Back', self, triggered=self.browser.back))
navBar.addAction(QAction(QIcon(':/images/next.png'), 'Forward', self, triggered=self.browser.forward))
navBar.addAction(QAction(QIcon(':/images/close.png'), 'Stop', self, triggered=self.browser.stop))
navBar.addAction(QAction(QIcon(':/images/reload.png'), 'Reload', self, triggered=self.browser.reload))
navBar.addSeparator()
navBar.addWidget(self.editUrl)
#瀏覽器相應url地址的變化
self.browser.urlChanged.connect(self.renewUrl)
def navigateToUrl(self):
url = QUrl(self.editUrl.text())
if url.scheme() == '':
url.setScheme('http')
self.browser.setUrl(url)
def renewUrl(self, url):
# 將當前網(wǎng)頁的鏈接更新到地址欄
self.editUrl.setText(url.toString())
self.editUrl.setCursorPosition(0)
if __name__ == '__main__':
app = QApplication(sys.argv)
window = DemoBrowser()
window.show()
sys.exit(app.exec())
運行效果如下圖:
使用QWebEngineView實現(xiàn)一個簡單的瀏覽器
前一篇: 實戰(zhàn)PyQt5: 132-一個輕量級的地圖應用
請多多關注,評論,收藏,點贊,和轉(zhuǎn)發(fā)。
文主要以 HackerScreenSaver 新功能的開發(fā)經(jīng)歷介紹 webBrowser中網(wǎng)頁如何調(diào)用.NET方法的過程。
之前開源了一款名為 HackerScreenSaver 的 Windows 屏保程序。該程序具有模擬黑客炫酷界面的特點,用戶可以將自定義的網(wǎng)頁作為鎖屏界面。不久前,有網(wǎng)友提出一個有趣的需求:能否在退出屏保時需要輸入密碼?雖然我不太清楚他的用意,但這個其實可以安排,不過需要變通一下。
之前做這個程序的時候我就發(fā)現(xiàn),屏幕保護程序需要自己處理退出,如果屏保程序設計得不夠合理,可能會導致用戶在無法正常退出屏保時遇到困擾。所以在設計之初,我添加了 MouseKeyHook
用來監(jiān)聽全局的鍵鼠事件。
那么設計新的功能來實現(xiàn)網(wǎng)友的需求也很簡單,當然不是直接的設計什么密碼輸入,然后判斷退出的功能。這里只需將屏保退出的功能提供給網(wǎng)頁控制就可以了。
之前介紹到為了程序簡易軟件采用了 webBrowser,那么為了讓網(wǎng)頁可以決定什么時候退出屏保,就需要讓 webBrowser 中的網(wǎng)頁可以調(diào)用 .NET 的方法。
在網(wǎng)頁中,我們需要在屏保退出的邏輯部分添加一段 JavaScript 代碼,用于調(diào)用 .NET 方法。這段代碼的核心是 window.external
對象,它允許 JavaScript 訪問 .NET 對象。我們在用戶輸入正確密碼或者游戲勝利等條件下執(zhí)行下面的 JavaScript 代碼即可:
window.external.ExecuteExitSrc();
對于 .NET 代碼,可以創(chuàng)建一個和單獨的類以供 web 調(diào)用:
[ComVisible(true)]
public class JavaScriptInteraction
{
public void ExecuteExitSrc()
{
Application.Exit();
}
}
需要注意的是,我們需要在該類上添加一個 [ComVisible(true)]
特性。這個特性使得該類的公共成員可以被 COM 組件訪問,從而實現(xiàn) JavaScript 與 .NET 方法之間的互操作,否則你會收到下面的錯誤信息:
System.ArgumentException:“ObjectForScripting 的類必須對 COM 可見。請確認該對象是公共的,或考慮向您的類添加 ComVisible 特性。”
最后,需要在 webBrowser
控件的 ObjectForScripting
屬性中設置一個 .NET 對象,這個對象將用于被 JavaScript 調(diào)用:
webB.ObjectForScripting = new JavaScriptInteraction();
為了演示新功能的使用,在 html 目錄中,提供了一個演示用的 exit.html
直接提供了網(wǎng)頁退出屏保的演示按鈕。
新的功能提供了更多的可玩性,用戶可以根據(jù)自己的喜好設計各種有意思的屏保,這樣也是滿足了輸入密碼退出這個功能的實現(xiàn)基礎。當然我們可以有許多有意思的功能可以自行設計,比如:
1.解謎屏保:設計一個帶有簡單謎題的屏保,用戶需要在網(wǎng)頁上回答正確才能退出屏保。謎題可以是數(shù)學題、邏輯題或者常識題等,每次屏保激活時,可以隨機從題庫中抽取一道題目。既然是題庫,甚至可以利用屏保學習各種知識,比如英語單詞,各種考試題等等。2.拼圖屏保:制作一個拼圖游戲,用戶需要在網(wǎng)頁上完成拼圖才能退出屏保。可以使用用戶自己的照片作為拼圖素材,或者從網(wǎng)上隨機抓取圖片。拼圖難度可以根據(jù)用戶的喜好進行調(diào)整。3.計時屏保:設置一個倒計時屏保,用戶需要在網(wǎng)頁上等待一段時間(例如,1分鐘)后才能退出屏保。在等待期間,可以展示一些有趣的事物,如名言警句、美麗的圖片或者實時新聞等。
通過這些有趣的屏保設計方案,用戶在退出屏保時可以享受到更多互動和趣味性。此外,這些方案還可以根據(jù)用戶的喜好和需求進行定制和擴展,為用戶帶來更豐富的屏保體驗。
同時,我還在更新中提供了一個經(jīng)典的 2048 小游戲,要求玩家在贏得游戲后才能退出屏保。
這個游戲改的邏輯其實是沒有改好的,也懶得調(diào)整了,更新一下游戲介紹也是可以的。
當玩家在游戲中努力拼搏,最終贏得游戲時,他們可能會發(fā)現(xiàn),游戲并沒有因此結(jié)束,屏保依然繼續(xù)運行。這時,他們可能會意識到,即使付出了努力,結(jié)果也不一定如人意。而當玩家選擇投降并重新開始游戲10次后,他們將發(fā)現(xiàn)這個看似無用的操作竟然讓屏保退出,讓電腦恢復正常使用。
也許只有努力過才會發(fā)現(xiàn),游戲還是投降躺平舒服些,只需要重開十次,就會被比你努力湊齊 2048 贏得游戲來退出屏保更快。人生有時就是這樣,在現(xiàn)實生活中,我們往往會面臨兩種選擇:努力拼搏還是躺平投降。有時候,努力拼搏的結(jié)果并不一定能讓我們達到預期的目標,反而可能讓我們陷入更深困境,帶來更多的困擾。而在某些情況下,選擇躺平投降,反而能讓我們以更輕松的心態(tài)面對問題,從而找到解決問題的更快方法。當然,該拼搏的時候,還是需要努力一把,萬一就成功了呢?
本文向大家介紹了如何在 webBrowser 中的網(wǎng)頁調(diào)用 .NET 方法,以及如何在屏保程序中加入游戲元素。通過這些技巧,我們可以為用戶帶來更有趣的屏保體驗。希望本文能對大家有所幫助,最后項目地址是:https://github.com/sangyuxiaowu/HackerScreenSaver?wt.mc_id=DT-MVP-5005195 感興趣的話,可以下載體驗一下。
*請認真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。