Browse Source

第一次提交

LiuLiu 1 year ago
commit
d4f306106b
4 changed files with 138 additions and 0 deletions
  1. 0 0
      __init__.py
  2. 80 0
      __main__.py
  3. 12 0
      core/listener.py
  4. 46 0
      core/recorder.py

+ 0 - 0
__init__.py


+ 80 - 0
__main__.py

@@ -0,0 +1,80 @@
+import asyncio
+import json
+import argparse
+import os
+import time
+import traceback
+
+from bilibili_api import settings
+
+from core.listener import Listener
+from core.recorder import Recorder
+import aiohttp
+import bilibili_api
+
+ROOM_DISPLAY_ID=22647787
+
+def print_json(data):
+    print(json.dumps(data, sort_keys=True, indent=4, separators=(', ', ': '), ensure_ascii=False))
+
+def startRecoder(_id,outputNameTemplate):
+    print('监听到房间'+str(_id)+'正在直播,开始录制!')
+    Recorder(_id).start(outputNameTemplate,True)
+
+
+if __name__ == '__main__':
+    parser = argparse.ArgumentParser()
+    parser.add_argument("ids",type=int,nargs="+")
+    parser.add_argument("--file-name-template",type=str,default='【${qn_desc}】${name} - ${datetime}')
+    parser.add_argument("--log",type=bool,default=True)
+
+    args = parser.parse_args()
+
+    print('启动中...')
+
+    proxy = os.getenv("https_proxy") or os.getenv("http_proxy")
+
+    if proxy!=None:
+        settings.proxy = proxy
+
+    while True:
+        try:
+            listener = Listener()
+            for _id in args.ids:
+                print('正在设置对房间'+str(_id)+'的监听...')
+                try:
+                    listener.add(_id,lambda :startRecoder(_id,args.file_name_template))
+                except bilibili_api.exceptions.ResponseCodeException as e:
+                    if e.code == 60004:
+                        print('房间'+str(_id)+'不存在!')
+                    elif e.code == 403:
+                        raise e
+        except bilibili_api.exceptions.NetworkException as e:
+            print('网络错误:',end='')
+            print(e)
+            time.sleep(1)
+        except aiohttp.client_exceptions.ClientConnectorError as e:
+            print('网络错误:',end='')
+            print(e)
+            time.sleep(1)
+        except bilibili_api.exceptions.ResponseCodeException as e:
+            if(e.code == 403):
+                print('获取直播间信息权限被禁止,将于30分钟后重试...')
+                time.sleep(1800)
+                print('正在重新尝试获取直播间信息...')
+            else:
+                time.sleep(1)
+        except Exception as e:
+            traceback.print_exc()
+            asyncio.get_event_loop().stop()
+            time.sleep(60)
+        else:
+            print('启动完毕')
+            asyncio.get_event_loop().run_forever()
+
+    # listener = Listener()
+    # for _id in args.ids:
+    #     print('正在设置对房间'+str(_id)+'的监听...')
+    #     listener.add(_id,lambda :startRecoder(_id,args.file_name_template))
+    # print('启动完毕')
+    # asyncio.get_event_loop().run_forever()

+ 12 - 0
core/listener.py

@@ -0,0 +1,12 @@
+import asyncio
+from bilibili_api import live
+
+class Listener:
+    def __checkLiveRoomStatus(self,room_display_id):
+        return asyncio.get_event_loop().run_until_complete(live.LiveRoom(room_display_id=room_display_id).get_room_play_info())["live_status"]
+
+    def add(self,room_display_id,liveHandler):
+        liveDanmaku = live.LiveDanmaku(room_display_id=room_display_id)
+        liveDanmaku.add_event_listener(name="LIVE", handler=liveHandler)
+        if self.__checkLiveRoomStatus(room_display_id=room_display_id)==1:
+            liveHandler()

+ 46 - 0
core/recorder.py

@@ -0,0 +1,46 @@
+import asyncio
+from datetime import datetime
+from string import Template
+
+from bilibili_api import live
+import ffmpy3
+
+class Recorder:
+    def __init__(self,room_display_id):
+        self.ROOM_DISPLAY_ID=room_display_id
+
+    async def __getInfoAndUrl(self,l):
+        return await l.get_room_info(), await l.get_room_play_url(live.ScreenResolution.FOUR_K)
+
+    def start(self, outputNameTemplate: str = '【${qn_desc}】${name} - ${datetime}', log: bool = True):
+        OUTPUT_NAME_TEMPLATE=Template(outputNameTemplate)
+        l = live.LiveRoom(room_display_id=self.ROOM_DISPLAY_ID)
+        info, play_url = asyncio.get_event_loop().run_until_complete(self.__getInfoAndUrl(l))
+        anchor_info=info["anchor_info"]["base_info"]
+        current_qn = play_url["current_qn"]
+        quality_descriptions = play_url["quality_description"]
+        durl = play_url["durl"]
+        current_qn_desc = "未知清晰度"
+        for quality_description in quality_descriptions:
+            if(current_qn == quality_description["qn"]):
+                current_qn_desc = quality_description["desc"]
+        url = durl[len(durl)-1]["url"]
+        outputName = OUTPUT_NAME_TEMPLATE.safe_substitute({
+            'name': anchor_info["uname"],
+            'qn_desc': current_qn_desc,
+            'datetime': datetime.now().isoformat()
+        })
+        f_handler=open(outputName+'.log', 'w') if log else asyncio.subprocess.PIPE
+        self.ff = ffmpy3.FFmpeg(
+            inputs={url:" -v debug"},
+            outputs={outputName+".flv":"-c copy -y"}
+        )
+        self.process = self.ff.run_async(stdout=f_handler, stderr=f_handler)
+        print(self.ff.cmd)
+        asyncio.get_event_loop().run_until_complete(self.process)
+        asyncio.get_event_loop().run_until_complete(self.ff.wait())
+        print(self.process)
+        
+    
+    def stop(self):
+        self.process.terminate()