最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

用Python實現(xiàn)一個模仿UP主彈幕控制的直播間功能

 更新時間:2021年12月03日 08:36:22   作者:蠻三刀醬  
up主通過代碼實現(xiàn)了實時讀取直播間里的彈幕內容,進而控制自己的電腦,把彈幕翻譯成指令操控《賽博朋克2077》游戲,這篇文章主要介紹了用Python實現(xiàn)一個模仿UP主彈幕控制的直播間功能,需要的朋友可以參考下

靈感來源

之前在B站看到一個有意思的視頻:

【B站】【亦】終極云游戲!五千人同開一輛車,復現(xiàn)經(jīng)典群體智慧實驗

大家可以看看,很有意思。

up主通過代碼實現(xiàn)了實時讀取直播間里的彈幕內容,進而控制自己的電腦,把彈幕翻譯成指令操控《賽博朋克2077》游戲。

觀眾也越來越多,最后甚至還把直接間搞崩了(當然,其實是因為那天B站全站崩了)。

我十分好奇到底是怎么做到的。

外行看熱鬧,內行看門道,作為半個內行,我們就模仿UP主的想法,自己做一個。

所以今天我的目標就是復刻一個 通過彈幕控制直播間 的代碼,并且最終在自己的直播間開播。

先給大家看看最終我的成品小視頻:

【B站】模仿UP主,做一個彈幕控制的直播間!

看起來是不是很像樣了。

初版設計思路

首先在腦海里規(guī)劃一個大致的思路,如下圖:

這個思路看起來很簡單,不過還是得解釋一下,首先我們要搞清楚,彈幕的內容是怎么抓到的。

大部分我們常見的直播平臺,在瀏覽器端,彈幕都是通過WebSocket來推送給觀眾的。在手機平板等客戶端(非Web端),可能會有一些更加復雜的TCP進行彈幕的推送。

關于TCP的消息投遞,有個很好的文章,就是美團的這個:美團終端消息投遞服務Pike的演進之路

歸根結底,這些彈幕都是通過在客戶端和服務端建立長鏈接來實現(xiàn)的。

所以,我們需要做的就是用代碼作為客戶端,與直播平臺進行長鏈接。這樣就能拿到彈幕。

我們只是需要實現(xiàn)整個彈幕控制的流程,所以彈幕的抓取也不是本文的重點,我們來淘一個現(xiàn)成的輪子!在Github上一頓找,找到了一個非常不錯的開源庫,里面能夠獲取很多直播平臺的彈幕:

https://github.com/wbt5/real-url

獲取斗魚&虎牙&嗶哩嗶哩&抖音&快手等 58 個直播平臺的真實流媒體地址(直播源)和彈幕,直播源可在 PotPlayer、flv.js 等播放器中播放。

我們把代碼clone下來,運行main函數(shù),隨便輸入一個Bilibili直播間地址,就能拿到直播間實時的彈幕流:

代碼里把獲取到的一條條彈幕(包括用戶名)直接打印在了控制臺。

他是如何做到的呢?核心的Python代碼如下(不熟悉Python?不要緊,就當做偽代碼,很容易看懂):

wss_url = 'wss://broadcastlv.chat.bilibili.com/sub'
heartbeat = b'\x00\x00\x00\x1f\x00\x10\x00\x01\x00\x00\x00\x02\x00\x00\x00\x01\x5b\x6f\x62\x6a\x65\x63\x74\x20' \
                b'\x4f\x62\x6a\x65\x63\x74\x5d '
  heartbeatInterval = 60

@staticmethod
async def get_ws_info(url):
    url = 'https://api.live.bilibili.com/room/v1/Room/room_init?id=' + url.split('/')[-1]
    reg_datas = []
    async with aiohttp.ClientSession() as session:
        async with session.get(url) as resp:
            room_json = json.loads(await resp.text())
            room_id = room_json['data']['room_id']
            data = json.dumps({
                'roomid': room_id,
                'uid': int(1e14 + 2e14 * random.random()),
                'protover': 1
            }, separators=(',', ':')).encode('ascii')
            data = (pack('>i', len(data) + 16) + b'\x00\x10\x00\x01' +
                    pack('>i', 7) + pack('>i', 1) + data)
            reg_datas.append(data)

    return Bilibili.wss_url, reg_datas

它連上了Bilibili的直播彈幕WSS地址,也就是WebSocket地址,然后偽裝成客戶端,接受彈幕推送。

OK,做完了第一步,下一步就是用消息隊列將彈幕發(fā)送出來。開啟單獨的消費者接收彈幕。

為了實現(xiàn)上盡量簡單,就不上那些專業(yè)的消息隊列了,這里用了redis的list作為隊列,將彈幕內容放進去。

發(fā)送者核心代碼如下:

# 鏈接Redis
def init_redis():
    r = redis.Redis(host='localhost', port=6379, decode_responses=True)
    return r

# 消息發(fā)送者
async def printer(q, redis):
    while True:
        m = await q.get()
        if m['msg_type'] == 'danmaku':
            print(f'{m["name"]}:{m["content"]}')
            list_str = list(m["content"])
            print("彈幕拆分:", list_str)
            for char in list_str:
                if char.lower() in key_list:
                    print('推送隊列:', char.lower())
                    redis.rpush(list_name, char.lower())

完成了彈幕內容的發(fā)送后,需要寫一個消費者,消費這些彈幕,把里面的指令都提取出來。

并且,在消費者收到彈幕后,如何消費呢?我們需要一個能夠用代碼指令控制電腦的辦法。

咱繼續(xù)本著不造輪子的原則,找到了一個Python的自動化控制庫PyAutoGUI

PyAutoGUI is a cross-platform GUI automation Python module for human beings. Used to programmatically control the mouse & keyboard.

安裝上這個庫,在代碼中引入,便可以通過他的API控制電腦鼠標和鍵盤執(zhí)行對應的操作。簡直是完美??!

消費者(控制電腦)核心Python代碼如下:

# 鏈接Redis
def init_redis():
    r = redis.Redis(host='localhost', port=6379, decode_responses=True)
    return r

# 消費者
def control(key_name):
    print("key_name =", key_name)
    if key_name == None:
        print("本次無指令發(fā)出")
        return
    key_name = key_name.lower()
    # 控制電腦指令
    if key_name in key_list:
        print("發(fā)出指令", key_name)
        pyautogui.keyDown(key_name)
        time.sleep(press_sec)
        pyautogui.keyUp(key_name)
        print("結束指令", key_name)

if __name__ == '__main__':
    r = init_redis()
    print("開始監(jiān)聽彈幕消息, loop_sec =", loop_sec)
    while True:
        key_name = r.lpop(list_name)
        control(key_name)
        time.sleep(loop_sec)

ok,大功告成,我們打開彈幕發(fā)送隊列和消費者,這個不斷循環(huán)消費的隊列就開始運行了。一旦彈幕中有wsad這種控制游戲常用的按鍵,電腦就會自己給自己發(fā)出指令。

初版運行中的問題

我興沖沖的打開自己的B站直播間,開始調試,結果發(fā)現(xiàn)我還是太天真了。這個初版代碼暴露了非常多的問題。我們一個個來說下是什么問題,我是如何解決的。

指令不人性化

水友們其實很喜歡發(fā)送類似www dddd這類重復單詞(疊詞),但初版的實現(xiàn)只支持單個字幕,水友們發(fā)現(xiàn)不得勁,沒有作用后,就從直播間走了。

這點很容易解決,把彈幕內容拆分成每個單詞,然后再推送給隊列。

解決方法:拆解彈幕,把DDD,拆成D,D,D,發(fā)送個消費者。

危險指令

首先是玩家的指令超出了應該有的范圍。

在我把賽博朋克游戲打開,讓彈幕觀眾控制游戲里的開車時,有個神秘觀眾進了直播間,默默發(fā)了個“F”,然后。。。

然后游戲里的V(主角名)就從車里下來了,淦,我是讓你們開車的,不是讓你們下來和警察斗毆的。。。

解決方法:添加彈幕過濾器。

# 將彈幕進行拆分,只發(fā)送指定的指令給消費者
key_list = ('w', 's', 'a', 'd', 'j', 'k', 'u', 'i', 'z', 'x', 'f', 'enter', 'shift', 'backspace')
list_str = list(m["content"])
            print("彈幕拆分:", list_str)
            for char in list_str:
                if char.lower() in key_list:
                    print('推送隊列:', char.lower())
                    redis.rpush(list_name, char.lower())

上面兩個問題解決后,發(fā)送者就像下面這樣運行了:

彈幕指令堆積

這是個很大的問題,如果處理所有水友發(fā)送的全部彈幕指令,一定會存在消費不過來的問題。

解決方法:需要固定時間處理彈幕,其他拋棄。

if __name__ == '__main__':
    r = init_redis()
    print("開始監(jiān)聽彈幕消息, loop_sec =", loop_sec)
    while True:
        key_name = r.lpop(list_name)
        # 每次只取出一個指令,然后把list清空,也就是這個時間窗口內其他彈幕都扔掉!
        r.delete(list_name)
        control(key_name)
        time.sleep(loop_sec)

彈幕從發(fā)出到觀眾看到結果有延遲

在最開始的視頻里,你們也能感受到了,從觀眾的指令發(fā)出,到最終被觀眾看到,大概要經(jīng)歷5秒的延遲。其中,起碼有3秒,都是網(wǎng)絡直播流的延遲,這一點,很難去優(yōu)化。

回爐重造后的版本

經(jīng)過一系列調優(yōu)和涉及,我們的版本也算是從V0.1到了V0.2了。猛虎落淚。

下面是重構后的結構圖:

后記

在寫完這個項目后,我在直播間試了很多次,體驗已經(jīng)無限接近UP主當時的視頻了。我開播掛在那邊好久,但是,人氣最高的時候,也只有20幾個人,寥寥十幾條彈幕,還有很多是我發(fā)的。我還期望著觀眾能夠拉更多人進來一起玩呢,事與愿違啊。

由此可得出結論,我,先得有粉絲,才能玩得起來啊,嗚嗚嗚嗚。大家要是不介意,可以關注下我的B站賬號,也叫:蠻三刀醬。我會偶爾抽風發(fā)點有趣的技術視頻的。

本文實現(xiàn)的全部代碼已經(jīng)開源在了Github上,大家可以在自己的直播間里試試呀:

https://github.com/qqxx6661/live_comment_control_stream

到此這篇關于用Python實現(xiàn)一個模仿UP主彈幕控制的直播間功能的文章就介紹到這了,更多相關python彈幕控制的直播間內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • python數(shù)據(jù)分析之DataFrame內存優(yōu)化

    python數(shù)據(jù)分析之DataFrame內存優(yōu)化

    pandas處理幾百兆的dataframe是沒有問題的,但是我們在處理幾個G甚至更大的數(shù)據(jù)時,就會特別占用內存,對內存小的用戶特別不好,所以對數(shù)據(jù)進行壓縮是很有必要的,本文就介紹了python DataFrame內存優(yōu)化,感興趣的可以了解一下
    2021-07-07
  • python爬蟲入門教程之點點美女圖片爬蟲代碼分享

    python爬蟲入門教程之點點美女圖片爬蟲代碼分享

    這篇文章主要介紹了python爬蟲入門教程之點點美女圖片爬蟲代碼分享,本文以采集抓取點點網(wǎng)美女圖片為例,需要的朋友可以參考下
    2014-09-09
  • Selenium基于PIL實現(xiàn)拼接滾動截圖

    Selenium基于PIL實現(xiàn)拼接滾動截圖

    這篇文章主要介紹了Selenium基于PIL實現(xiàn)拼接滾動截圖,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • Python3.8如何解決No module named 'numpy'報錯問題

    Python3.8如何解決No module named 'numpy&apos

    這篇文章主要介紹了Python3.8如何解決No module named 'numpy'報錯問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • python+PyQt5 左右聲道測試源代碼

    python+PyQt5 左右聲道測試源代碼

    這篇文章主要介紹了python+PyQt5 左右聲道測試源代碼,左聲道,人機交互測試,點擊右邊聽到的對應序號按鈕,對python左右聲道測試感興趣的朋友一起看看吧
    2024-02-02
  • python創(chuàng)建一個最簡單http webserver服務器的方法

    python創(chuàng)建一個最簡單http webserver服務器的方法

    這篇文章主要介紹了python創(chuàng)建一個最簡單http webserver服務器的方法,實例分析了Python操作http創(chuàng)建服務器端的相關技巧,需要的朋友可以參考下
    2015-05-05
  • 詳解python架構?PyNeuraLogic超越Transformers

    詳解python架構?PyNeuraLogic超越Transformers

    這篇文章主要為大家介紹了python使用?PyNeuraLogic超越Transformers示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-03-03
  • Python提取JSON格式數(shù)據(jù)實戰(zhàn)案例

    Python提取JSON格式數(shù)據(jù)實戰(zhàn)案例

    這篇文章主要給大家介紹了關于Python提取JSON格式數(shù)據(jù)的相關資料, Python提供了內置的json模塊,用于處理JSON數(shù)據(jù),文中給出了詳細的代碼示例,需要的朋友可以參考下
    2023-07-07
  • Python之字典對象的幾種創(chuàng)建方法

    Python之字典對象的幾種創(chuàng)建方法

    這篇文章主要介紹了Python之字典對象的幾種創(chuàng)建方法,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • 詳解Django項目中模板標簽及模板的繼承與引用(網(wǎng)站中快速布置廣告)

    詳解Django項目中模板標簽及模板的繼承與引用(網(wǎng)站中快速布置廣告)

    這篇文章主要介紹了詳解Django項目中模板標簽及模板的繼承與引用【網(wǎng)站中快速布置廣告】,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-03-03

最新評論

南郑县| 池州市| 宜城市| 金坛市| 板桥市| 保亭| 镇巴县| 邵阳县| 香河县| 阿瓦提县| 抚宁县| 祁阳县| 曲周县| 临邑县| 甘谷县| 翁源县| 土默特右旗| 长寿区| 尉氏县| 石河子市| 南开区| 城固县| 利津县| 许昌县| 宁波市| 南木林县| 开化县| 宣恩县| 芷江| 恭城| 靖州| 正镶白旗| 安溪县| 宿州市| 平和县| 宜城市| 大余县| 永泰县| 卢湾区| 昌乐县| 墨江|