📺Headless全自动B站直播录播、切片、上传一体工具

Overview

DDRecorder

Headless全自动B站直播录播、切片、上传一体工具

感谢

FortuneDayssss/BilibiliUploader

安装指南(Windows)

  1. 在Release下载zip包解压。
  2. 修改配置文件config.json
  3. 双击运行DDRecorder.exe (这将使用config.json)或 DDRecorder.exe <配置文件>

安装指南(MacOS/Linux)

  1. 安装Python >= 3.7 https://www.python.org/downloads/release/python-386/
  2. 安装ffmpeg https://ffmpeg.org/download.html
  3. 执行pip install -r requirements.txt
  4. 修改config文件夹下的配置文件config.json
  5. 执行python main.py <配置文件>

配置文件字段解释

全局设置(root部分)

  • check_interval: 直播间开播状态检查间隔,单位为秒,每个监控直播间单独计数,因此如果监控直播间较多,建议适当调大。由于B站API访问次数限制,建议不要小于30。默认:100
  • print_interval:控制台消息打印间隔,单位为秒。
  • data_path: 数据文件路径。默认:"./"(即程序所在路径)
  • logger: 日志相关设置
    • log_path: 日志文件路径。默认:"./log"
    • log_level: 日志级别,可选DEBUG\INFO\WARN
  • request_header: 请求时使用的头。代码中已经包含了一个默认的,在这里进行调整将会覆盖默认值,如无必要请留空。
  • uploader: 上传器相关设置
    • upload_by_edit:通过编辑稿件的方法上传多P切片,可以让后续分P上传时让前面的分P进入审核队列,加快开放浏览的速度
    • thread_pool_workers: 上传时的线程池大小。默认:1
    • max_retry: 最大重试次数。默认:10
  • enable_baiduyun:是否开启百度云功能。

直播间特定设置(spec部分,此部分是一个数组,如果需要同时监控多个直播间,依次添加至数组中即可)

  • room_id: 房间号
  • recorder: 录制器相关设置
    • keep_raw_record: 是否保留原始录像(flv)文件(录制器最后会合并所有flv文件导出mp4)。默认:true
  • parser: 弹幕分析器相关设置
    • interval: 弹幕计数间隔,单位秒。默认:30.
    • up_ratio: 开始切片位置弹幕数量与上一个时段弹幕数量之比的阈值。默认:2.5
    • down_ratio: 结束切片位置弹幕数量与上一个时段弹幕数量之比的阈值。默认:0.75
    • topK: 提取弹幕关键词的数量。默认:5
  • clipper: 切片器相关设置
    • enable_clipper: 启用切片功能。默认:true
    • min_length: 切片最短长度,单位秒。默认:60
    • start_offset: 切片开始时间偏移量,正为向后偏移,负为向前偏移,单位秒。默认:0。建议根据直播间弹幕延迟调整。
    • end_offset: 切片结束时间偏移量,正为向后偏移,负为向前偏移,单位秒。默认:0。建议根据直播间弹幕延迟调整。
  • uploader: 上传器相关设置
    • account: 上传账户信息
      • username: 用户名
      • password: 密码
    • record: 录播上传设置
      • upload_record: 是否上传录播。默认:true
      • keep_record_after_upload: 是否在上传过审后保留录播。默认:true
      • split_interval: 录播划分间隔,单位秒。由于B站无法一次上传大文件,因此长录播需要分片才能上传。默认:3600。如设为0,表示不划分,如此请保证账号具有超大文件权限。
      • title:上传视频的标题,可以用 {date} 标识日期
      • tid:分区编号,可在 https://github.com/FortuneDayssss/BilibiliUploader/wiki/Bilibili%E5%88%86%E5%8C%BA%E5%88%97%E8%A1%A8 查询
      • tags:上传视频的标签
      • desc:上传视频的描述,可以用 {date} 标识日期
    • clippers: 自动切片上传设置
  • backup:是否将录像备份到百度云。
Comments
  • BUG 反馈 FFmpeg合成失败

    BUG 反馈 FFmpeg合成失败

    结论:猜测是FFmpeg合成环节的问题,没有这个库的使用经验,寻求帮助。

    日志如下:

    路径:

    
    ./data/cred/ # 正常
    ./data/merged/ # 异常,无合成后文件
    ./data/danmu/ # 正常
    ./data/records/ # 正常,有大量 *.flv 文件生成
    ./data/splits/ # 异常,无输出
    ./data/outputs/ # 异常,无输出
    ./data/merge_confs/*_merge_conf.txt # 异常,文件写入为空
    
    

    Processor 日志

    
    Thu, 15 Dec 2022 17:32:07 139918016505600 Thread-4 bili_webup.py[line:555] INFO 用户权重: 1
    Thu, 15 Dec 2022 17:32:07 139918016505600 Thread-4 bili_webup.py[line:578] INFO 使用客户端api端提交
    Thu, 15 Dec 2022 17:32:07 139918016505600 Thread-4 connectionpool.py[line:228] DEBUG Starting new HTTP connection (1): member.bilibili.com:80
    Thu, 15 Dec 2022 17:32:07 139918016505600 Thread-4 connectionpool.py[line:456] DEBUG http://member.bilibili.com:80 "POST /x/vu/client/add?access_key={token} HTTP/1.1" 200 None
    Thu, 15 Dec 2022 17:32:07 139918016505600 Thread-4 Uploader.py[line:140] ERROR [Site:BiliBili Room:{id}] Error while uploading:{'code': 21011, 'message': '新增稿件分P不能为空', 'ttl': 1}Traceback (most recent call last):
      File "/usr/src/app/Uploader.py", line 132, in upload
        record_video_ret = self.uploader.submit()
      File "/usr/local/lib/python3.10/site-packages/biliup/plugins/bili_webup.py", line 570, in submit
        raise Exception(ret)
    Exception: {'code': 21011, 'message': '新增稿件分P不能为空', 'ttl': 1}
    
    

    FFmpeg 日志

    
    ffmpeg version 4.3.5-0+deb11u1 Copyright (c) 2000-2022 the FFmpeg developers
      built with gcc 10 (Debian 10.2.1-6)
      configuration: --prefix=/usr --extra-version=0+deb11u1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libdav1d --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librabbitmq --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libsrt --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-pocketsphinx --enable-libmfx --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
      libavutil      56. 51.100 / 56. 51.100
      libavcodec     58. 91.100 / 58. 91.100
      libavformat    58. 45.100 / 58. 45.100
      libavdevice    58. 10.100 / 58. 10.100
      libavfilter     7. 85.100 /  7. 85.100
      libavresample   4.  0.  0 /  4.  0.  0
      libswscale      5.  7.100 /  5.  7.100
      libswresample   3.  7.100 /  3.  7.100
      libpostproc    55.  7.100 / 55.  7.100
    
    ./data/merge_confs/24402390_2022-12-15_11-49-21_merge_conf.txt: Invalid data found when processing input
    
    
    opened by yuki1sntSnow 9
  • 编译出的DDRecorder.exe无法正常运行

    编译出的DDRecorder.exe无法正常运行

    打开DDRecorder.exe后

    Traceback (most recent call last):
      File "main.py", line 12, in <module>
      File "PyInstaller\loader\pyimod03_importers.py", line 476, in exec_module
      File "MainRunner.py", line 12, in <module>
      File "PyInstaller\loader\pyimod03_importers.py", line 476, in exec_module
      File "DanmuRecorder.py", line 13, in <module>
      File "PyInstaller\loader\pyimod03_importers.py", line 476, in exec_module
      File "brotli\__init__.py", line 3, in <module>
      File "PyInstaller\loader\pyimod03_importers.py", line 476, in exec_module
      File "brotli\brotli.py", line 5, in <module>
    ModuleNotFoundError: No module named '_cffi_backend'
    [24396] Failed to execute script 'main' due to unhandled exception!
    

    大概是封包时cffi模组出错

    opened by BuArcher 6
  • 上传成功后不会自动删除录播文件

    上传成功后不会自动删除录播文件

    使用的是latest(edba21222ad1224916cb22a0c3c4f0dcf7572099)编译的Docker版跑在Ubuntu18.04上。 config.json里已经设置"keep_raw_record" : false"keep_record_after_upload": false 今天发现昨天的录播上传成功且过审之后,数据文件夹内records是没有没有视频文件的(应该是"keep_raw_record" : false参数起了作用),但merged文件夹内保留了完整的录像mp4文件以及splits文件夹内保留了所有split的mp4文件,"keep_record_after_upload": false参数并没有起到作用。

    完整的config.json如下:

    {
      "root": {
        "check_interval": 120,
        "print_interval": 10,
        "data_path": "/downloads",
        "logger": { "log_path": "/app/log", "log_level": "DEBUG" },
        "request_header": {},
        "uploader": {
          "upload_by_edit": true,
          "thread_pool_workers": 4,
          "max_retry": 10
        },
        "enable_baiduyun": false
      },
      "spec": [
        {
          "room_id": "22637920",
          "recorder": { "keep_raw_record": false },
          "parser": {
            "interval": 30,
            "up_ratio": 2.5,
            "down_ratio": 0.75,
            "topK": 5
          },
          "clipper": {
            "enable_clipper": false,
            "min_length": 60,
            "start_offset": -20,
            "end_offset": 10
          },
          "uploader": {
            "account": {
              "username": "xxxxxx",
              "password": "xxxxxx"
            },
            "copyright": 2,
            "record": {
              "upload_record": true,
              "keep_record_after_upload": false,
              "split_interval": 3600,
              "title": "{date} 直播录播",
              "tid": 65,
              "tags": ["直播录播"],
              "desc": "本视频由全自动切片型智能DD机剪辑上传~"
            },
            "clips": {
              "upload_clips": false,
              "keep_clips_after_upload": false,
              "title": "{date} 直播精彩剪辑【自动切片】",
              "tid": 65,
              "tags": ["直播录播"],
              "desc": "本视频由全自动切片型智能DD机剪辑上传~"
            }
          },
          "backup": false
        }
      ]
    }
    
    
    bug 
    opened by gabriel254 6
  • 上传时间过久

    上传时间过久

    系统环境Ubuntu20

    录播下载完成后显示运行ffmpeg,状态显示正在处理视频。 处理完毕后状态显示为正在上传至BiliBIli 弹出如下

    upload 31384_2022-03-25_09-24-41_0001.mp4 added in pool chunk0/1156 filename: 31384_2022-03-25_09-24-41_0000.mp4 200

    该chunk值增加缓慢(超过一小时该主播录播未上传完毕) 后台显示上传速率10~20M左右

    机器位于LV,带宽1000M,使用biliup-rs测试选择kodo线路,单文件并发上传数3~6可以跑满至900M 猜测时候是上传时选择了其他线路问题 不知如何更改,且不确定问题原因

    opened by infinity-M 5
  • v1.3.0版源码,docker换源build成功,按照文档配置config,代码报错。

    v1.3.0版源码,docker换源build成功,按照文档配置config,代码报错。

    build成功后,代码部分的报错

    Building recorder
    Step 1/9 : FROM python:3.11
     ---> ee4e7a0f1c35
    Step 2/9 : ADD apt/sources.list /etc/apt/sources.list
     ---> Using cache
     ---> 7899a0349dc1
    Step 3/9 : RUN apt-get update && apt-get install -y ffmpeg
     ---> Using cache
     ---> a24430cf1f78
    Step 4/9 : WORKDIR /usr/src/app
     ---> Using cache
     ---> 30316c42eaf0
    Step 5/9 : COPY requirements.txt ./
     ---> Using cache
     ---> 597271336cc9
    Step 6/9 : RUN python3 -m pip install --upgrade pip &&     pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
     ---> Using cache
     ---> e83fc5c926c3
    Step 7/9 : RUN pip install --no-cache-dir -r requirements.txt
     ---> Using cache
     ---> 20b2f3513345
    Step 8/9 : COPY . .
     ---> c34a39f5a5bc
    Step 9/9 : CMD ["python3", "-u", "main.py", "config/config.json"]
     ---> Running in eb9fd173b66f
    Removing intermediate container eb9fd173b66f
     ---> 5c1e991f0e0d
    Successfully built 5c1e991f0e0d
    Successfully tagged ddrecorder-130_recorder:latest
    Recreating ddrecorder-130_recorder_1 ... done
    Attaching to ddrecorder-130_recorder_1
    recorder_1  | Traceback (most recent call last):
    recorder_1  |   File "/usr/src/app/main.py", line 11, in <module>
    recorder_1  |     import utils
    recorder_1  |   File "/usr/src/app/utils.py", line 12, in <module>
    recorder_1  |     from fastHan import FastHan
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastHan/__init__.py", line 7, in <module>
    recorder_1  |     from .FastModel import FastHan,Sentence,Token
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastHan/FastModel.py", line 6, in <module>
    recorder_1  |     from fastNLP import Trainer, Vocabulary
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastNLP/__init__.py", line 3, in <module>
    recorder_1  |     from fastNLP.core import *
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastNLP/core/__init__.py", line 114, in <module>
    recorder_1  |     from .callbacks import *
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastNLP/core/callbacks/__init__.py", line 41, in <module>
    recorder_1  |     from .torch_callbacks import *
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastNLP/core/callbacks/torch_callbacks/__init__.py", line 8, in <module>
    recorder_1  |     from .torch_grad_clip_callback import TorchGradClipCallback
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastNLP/core/callbacks/torch_callbacks/torch_grad_clip_callback.py", line 6, in <module>
    recorder_1  |     from ...drivers.torch_driver.fairscale import FairScaleDriver
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastNLP/core/drivers/__init__.py", line 30, in <module>
    recorder_1  |     from .torch_driver import TorchDriver, TorchSingleDriver, TorchDDPDriver, DeepSpeedDriver, FairScaleDriver, \
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastNLP/core/drivers/torch_driver/__init__.py", line 18, in <module>
    recorder_1  |     from .torch_fsdp import TorchFSDPDriver
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/fastNLP/core/drivers/torch_driver/torch_fsdp.py", line 7, in <module>
    recorder_1  |     from torch.distributed.fsdp import FullyShardedDataParallel, StateDictType, FullStateDictConfig, OptimStateKeyType
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/fsdp/__init__.py", line 1, in <module>
    recorder_1  |     from .flat_param import FlatParameter
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/fsdp/flat_param.py", line 26, in <module>
    recorder_1  |     from ._fsdp_extensions import _ext_post_unflatten_transform, _ext_pre_flatten_transform
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/fsdp/_fsdp_extensions.py", line 7, in <module>
    recorder_1  |     from torch.distributed.fsdp._shard_utils import _create_chunk_sharded_tensor
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/fsdp/_shard_utils.py", line 10, in <module>
    recorder_1  |     from torch.distributed._shard.sharded_tensor import (
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/_shard/__init__.py", line 1, in <module>
    recorder_1  |     from .api import (
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/_shard/api.py", line 6, in <module>
    recorder_1  |     from torch.distributed._shard.sharded_tensor import (
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/_shard/sharded_tensor/__init__.py", line 8, in <module>
    recorder_1  |     import torch.distributed._shard.sharding_spec as shard_spec
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/_shard/sharding_spec/__init__.py", line 1, in <module>
    recorder_1  |     from .api import (
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/_shard/sharding_spec/api.py", line 16, in <module>
    recorder_1  |     import torch.distributed._shard.sharded_tensor.metadata as sharded_tensor_meta
    recorder_1  |   File "/usr/local/lib/python3.11/site-packages/torch/distributed/_shard/sharded_tensor/metadata.py", line 70, in <module>
    recorder_1  |     @dataclass
    recorder_1  |      ^^^^^^^^^
    recorder_1  |   File "/usr/local/lib/python3.11/dataclasses.py", line 1221, in dataclass
    recorder_1  |     return wrap(cls)
    recorder_1  |            ^^^^^^^^^
    recorder_1  |   File "/usr/local/lib/python3.11/dataclasses.py", line 1211, in wrap
    recorder_1  |     return _process_class(cls, init, repr, eq, order, unsafe_hash,
    recorder_1  |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    recorder_1  |   File "/usr/local/lib/python3.11/dataclasses.py", line 959, in _process_class
    recorder_1  |     cls_fields.append(_get_field(cls, name, type, kw_only))
    recorder_1  |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    recorder_1  |   File "/usr/local/lib/python3.11/dataclasses.py", line 816, in _get_field
    recorder_1  |     raise ValueError(f'mutable default {type(f.default)} for field '
    recorder_1  | ValueError: mutable default <class 'torch.distributed._shard.sharded_tensor.metadata.TensorProperties'> for field tensor_properties is not allowed: use default_factory
    
    

    以下是 config 配置,按照文档填写(隐去账户信息),是否和配置有关?

    {
      "root": {
        "check_interval": 60,
        "print_interval": 10,
        "data_path": "./",
        "logger": { "log_path": "./log", "log_level": "DEBUG" },
        "request_header": {},
        "uploader": {
          "upload_by_edit": true,
          "thread_pool_workers": 1,
          "max_retry": 30,
          "lines":"AUTO"
        },
        "enable_baiduyun": false
      },
      "spec": [
        {
          "room_id": "000",
          "recorder": { "keep_raw_record": false },
          "parser": {
            "interval": 30,
            "up_ratio": 2.5,
            "down_ratio": 0.75,
            "topK": 5
          },
          "clipper": {
            "enable_clipper": true,
            "min_length": 30,
            "start_offset": -20,
            "end_offset": 10
          },
          "manual_clipper": {
            "enabled": true,
            "uid": "000"
          },
          "uploader": {
            "account": {
              "username": "1",
              "password": "2",
              "access_token": "3",
              "refresh_token": "4",
              "cookies": {
                "SESSDATA": "5",
                "bili_jct": "6",
                "DedeUserID": "7",
                "DedeUserID__ckMd5": "8",
                "sid": "9"
              }
            },
            "copyright": 2,
            "record": {
              "upload_record": true,
              "keep_record_after_upload": true,
              "split_interval": 3600,
              "title": "【TEST】{date}直播录播",
              "tid": 27,
              "tags": ["直播录播", "虚拟主播", "VTuber", "虚拟UP主"],
              "desc": "切片自{date} 直播\n---------------------------------------\n自用",
              "cover": ""
            },
            "clips": {
              "upload_clips": true,
              "keep_clips_after_upload": false,
              "title": "{date}直播精彩剪辑【自动切片】",
              "tid": 27,
              "tags": ["直播录播", "虚拟主播", "VTuber", "虚拟UP主"],
              "desc": "切片自 {date} 自用",
              "cover": ""
            }
          },
          "backup": false
        }
      ]
    }
    
    
    opened by yuki1sntSnow 4
  • 在CentOS 7.9下安装时报错 ERROR: Can not execute `setup.py` since setuptools is not available in the build environment.

    在CentOS 7.9下安装时报错 ERROR: Can not execute `setup.py` since setuptools is not available in the build environment.

    via 阿里云ECS服务器 OS = CentOS 7.9 python = 3.10.2

    下面是报错细节 `[root@iZuf65sjhgk33mv8gbk7e2Z DDRecorder]# python -m pip install -r requirements.txt Looking in indexes: http://mirrors.cloud.aliyuncs.com/pypi/simple/ Collecting git+git://github.com/FortuneDayssss/BilibiliUploader.git (from -r requirements.txt (line 58)) Cloning git://github.com/FortuneDayssss/BilibiliUploader.git to /tmp/pip-req-build-wenebb5a Running command git clone --quiet git://github.com/FortuneDayssss/BilibiliUploader.git /tmp/pip-req-build-wenebb5a Resolved git://github.com/FortuneDayssss/BilibiliUploader.git to commit 23266861c155c75eae5a29a424a15d87da81c132 Preparing metadata (setup.py) ... error error: subprocess-exited-with-error

    × python setup.py egg_info did not run successfully. │ exit code: 1 ╰─> [1 lines of output] ERROR: Can not execute setup.py since setuptools is not available in the build environment. [end of output]

    note: This error originates from a subprocess, and is likely not a problem with pip. error: metadata-generation-failed

    × Encountered error while generating package metadata. ╰─> See above for output.

    note: This is an issue with the package mentioned above, not pip. hint: See above for details.`

    请问应该怎么解决?

    opened by Funny-ppt 3
  • 录制后无输出

    录制后无输出

    +--------+----------+---------+----------+--------------+---------------------+ | TID | 平台 | 房间号 | 直播状态 | 程序状态 | 状态变化时间 | +--------+----------+---------+----------+--------------+---------------------+ | 332887 | BiliBili | 1991211 | 否 | 正在处理视频 | 2022-06-13 18:33:36 | +--------+----------+---------+----------+--------------+---------------------+

    Traceback (most recent call last): File "/root/ddrecorder/DDRecorder-1.2.3/Processor.py", line 117, in concat ret = subprocess.run( File "/usr/lib/python3.8/subprocess.py", line 516, in run raise CalledProcessError(retcode, process.args, subprocess.CalledProcessError: Command 'ffmpeg -y -f concat -safe 0 -i ./data/merge_confs/1991211_2022-06-13_18-32-19_merge_conf.txt -c copy -fflags +igndts -avoid_negative_ts make_zero ./data/merged/1991211_2022-06-13_18-32-19_merged.mp4' returned non-zero exit status 1. Traceback (most recent call last): File "/root/ddrecorder/DDRecorder-1.2.3/Processor.py", line 239, in run ret = self.pre_concat() File "/root/ddrecorder/DDRecorder-1.2.3/Processor.py", line 180, in pre_concat self.live_start = self.times[0][0] IndexError: list index out of range 使用cookies上传 DDRecorder 当前时间:2022-06-13 18:34:39.711213 正在工作线程数:2

    outputs文件夹里啥也没有 records文件夹里有几个flv但是都是0字节的文件 不知道哪步错了呢 萌新一个 刚学着折腾 还请大佬指教一下x

    opened by Sakuranda 2
  • Fix: fix live_status out of sync

    Fix: fix live_status out of sync

    This is an attempt to #17

    我发现不仅会产生空目录,而且 proc_process 会产生大量异常。这些异常不会影响录播,据我的观察,它们大量发生于一次录播结束的时候,原因是 https://github.com/AsaChiri/DDRecorder/blob/336cc831480620b49b01f819a1dd00ebf5e98f6e/MainRunner.py#L66-L94 当 record_process 和 danmu_process 退出后,外面的 self.bl.live_status 还没有到更新周期,所以状态还是在播,就会又开始一次录制。它会一直不停地开始录制直到 self.bl.live_status 自轮询更新为止。

    尝试修复:通过代理模式继承 bl 的实例,这样内外的状态即是同步的

    待测试

    opened by satouriko 2
  • 录制正常,上传显示'新增稿件分P不能为空'

    录制正常,上传显示'新增稿件分P不能为空'

    下面是Processor的log Wed, 06 Jul 2022 22:07:22 140207663871552 Thread-3 Processor.py[line:273] INFO Processing clipper Wed, 06 Jul 2022 22:07:22 140207663871552 Thread-3 retry.py[line:351] DEBUG Converted retries value: 3 -> Retry(total=3, connect=None, read=None, redirect=None, status=None) Wed, 06 Jul 2022 22:07:22 140207663871552 Thread-3 connectionpool.py[line:1001] DEBUG Starting new HTTPS connection (1): api.live.bilibili.com:443 Wed, 06 Jul 2022 22:07:22 140207663871552 Thread-3 connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /room/v1/Room/get_info?room_id=1991211 HTTP/1.1" 200 None Wed, 06 Jul 2022 22:07:22 140207663871552 Thread-3 BiliLive.py[line:26] DEBUG [Site:BiliBili Room:1991211] 房间API消息:ok Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /live_user/v1/UserInfo/get_anchor_in_room?roomid=1991211 HTTP/1.1" 200 740 Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /room/v1/Room/get_info?room_id=1991211 HTTP/1.1" 200 None Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 BiliLive.py[line:26] DEBUG [Site:BiliBili Room:1991211] 房间API消息:ok Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /live_user/v1/UserInfo/get_anchor_in_room?roomid=1991211 HTTP/1.1" 200 740 Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 BaseLive.py[line:66] INFO [Site:BiliBili Room:1991211] 等待开播 Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:1001] DEBUG Starting new HTTPS connection (1): api.bilibili.com:443 Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:456] DEBUG https://api.bilibili.com:443 "GET /x/web-interface/nav HTTP/1.1" 200 None Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:1001] DEBUG Starting new HTTPS connection (1): member.bilibili.com:443 Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:456] DEBUG https://member.bilibili.com:443 "GET /x/geetest/pre/add HTTP/1.1" 200 None Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:228] DEBUG Starting new HTTP connection (1): api.bilibili.com:80 Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:456] DEBUG http://api.bilibili.com:80 "GET /x/space/myinfo HTTP/1.1" 200 None Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 bili_webup.py[line:547] INFO 用户权重: 1 Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 bili_webup.py[line:570] INFO 使用客户端api端提交 Wed, 06 Jul 2022 22:07:23 140207663871552 Thread-3 connectionpool.py[line:228] DEBUG Starting new HTTP connection (1): member.bilibili.com:80 Wed, 06 Jul 2022 22:07:24 140207663871552 Thread-3 connectionpool.py[line:456] DEBUG http://member.bilibili.com:80 "POST /x/vu/client/add?access_key=2780e54b8b72a27b69be55325f3cba71 HTTP/1.1" 200 None Wed, 06 Jul 2022 22:07:24 140207663871552 Thread-3 Uploader.py[line:132] ERROR [Site:BiliBili Room:1991211] Error while uploading:{'code': 21011, 'message': '新增稿件分P不能为空', 'ttl': 1}Traceback (most recent call last): File "/root/ddrec/DDRecorder-main/Uploader.py", line 86, in upload clips_video_ret = self.uploader.submit() File "/usr/local/lib/python3.10/dist-packages/biliup/plugins/bili_webup.py", line 562, in submit raise Exception(ret) Exception: {'code': 21011, 'message': '新增稿件分P不能为空', 'ttl': 1}

    opened by Sakuranda 1
  • fix: live status shadowing

    fix: live status shadowing

    很尴尬就是,#46 其实并没有真正解决 #17,但是让问题显著变少了。以前会出来一大堆空目录,现在每次录播只会多出来一个。原因是我在初始化 BiliLiveRecorderBiliDanmuRecorder 的时候挂载了 MainRunnerself.bl 的状态(上次检查的时间),这样子进程和父进程检查的时间相差变小了。并不是像我想象的那样,子进程对 self 中状态的修改能直接反馈给父进程。https://stackoverflow.com/a/40873071

    #47 也没有解决 #17,但是思路应该是对的。问题是不能直接通过给派生类属性赋值操作基类的属性(见下面示例代码),这个 Pr 提供了修复。

    class BaseClass:
        def __init__(self):
            self.__live_status = False
    
        @property
        def live_status(self) -> bool:
            return self.__live_status
    
        @live_status.setter
        def live_status(self, status: bool):
            self.__live_status = status
    
    
    class SubClass(BaseClass):
        def __init__(self):
            super().__init__()
    
    
    x = SubClass()
    x.__live_status = True
    # False
    print(x.live_status)
    x.live_status = True
    # True
    print(x.live_status)
    

    然后实际上,在这个 Pr 之前, https://github.com/AsaChiri/DDRecorder/blob/1ca39f94ea46c3eed12bad730f38862d19c31764/BiliLive.py#L16 甚至是没有用的,因为它并没有“check_live_status”,只是更新了“room_info”,“room_info”在第一次访问“live_status”属性之前又没有用到。 https://github.com/AsaChiri/DDRecorder/blob/1ca39f94ea46c3eed12bad730f38862d19c31764/BaseLive.py#L59-L67

    opened by satouriko 1
  • 录制结束上传报错

    录制结束上传报错

    Describe the bug A clear and concise description of what the bug is.

    **To Reproduc Steps to reproduce the behavior:

    1. Go to '...'
    2. Click on '....'
    3. Scroll down to '....'
    4. See error

    Expected behavior A clear and concise description of what you expected to happen.

    Screenshots If applicable, add screenshots to help explain your problem.

    Desktop (please complete the following information):

    • OS: [e.g. iOS]
    • Browser [e.g. chrome, safari]
    • Version [e.g. 22]

    Smartphone (please complete the following information):

    • Device: [e.g. iPhone6]
    • OS: [e.g. iOS8.1]
    • Browser [e.g. stock browser, safari]
    • Version [e.g. 22]

    Additional context Add any other context about the problem here.

    Traceback (most recent call last): File "/usr/src/app/Processor.py", line 118, in concat ret = subprocess.run( File "/usr/local/lib/python3.10/subprocess.py", line 526, in run raise CalledProcessError(retcode, process.args, subprocess.CalledProcessError: Command 'ffmpeg -y -f concat -safe 0 -i ./data/merge_confs/22637261_2022-12-28_13-00-33_merge_conf.txt -c copy -fflags +igndts -avoid_negative_ts make_zero ./data/merged/22637261_2022-12-28_13-00-33_merged.mp4' returned non-zero exit status 1. Traceback (most recent call last): File "/usr/src/app/Processor.py", line 251, in run ret = self.pre_concat() File "/usr/src/app/Processor.py", line 189, in pre_concat self.live_start = self.times[0][0] IndexError: list index out of range

    opened by TimothyChan44 0
  • 录制443报错

    录制443报错

    records文件夹下有大量flv文件,LiveRecoder日志文件中包含大量443报错 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread BiliLiveRecorder.py[line:24] INFO [Site:BiliBili Room:23371670] √ 正在录制...23371670 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread connectionpool.py[line:1003] DEBUG Starting new HTTPS connection (1): cn-cq-ct-01-12.bilivideo.com:443 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread connectionpool.py[line:456] DEBUG https://cn-cq-ct-01-12.bilivideo.com:443 "GET /live-bvc/972317/live_524076304_16608389.flv?expires=1671835902&pt=web&deadline=1671835902&len=0&oi=2883398179&platform=web&qn=10000&trid=100023ab06448de249c48d8ec473a0ccb9c1&uipk=100&uipv=100&nbs=1&uparams=cdn,deadline,len,oi,platform,qn,trid,uipk,uipv,nbs&cdn=cn-gotcha01&upsig=0e9d5b373df19803c365b1de604185b9&sk=d7a794fee632e64bb8422fd71c02c0da&p2p_type=0&src=57345&sl=1&free_type=0&sid=cn-cq-ct-01-12&chash=1&sche=ban&score=2&pp=rtmp&source=one&trace=8&site=b05a67226a1517c5a8736d7171ccc4bb&order=1 HTTP/1.1" 403 552 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread BiliLiveRecorder.py[line:59] INFO [Site:BiliBili Room:23371670] 录制完成./data/records/23371670_2022-12-24_05-34-16/23371670_2022-12-24_05-50-42.flv Sat, 24 Dec 2022 05:50:42 4603106816 MainThread BaseLive.py[line:84] DEBUG [Site:BiliBili Room:23371670] 间隔不足,使用过去状态 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /room/v1/Room/playUrl?cid=23371670&otype=json&quality=0&platform=web HTTP/1.1" 200 966 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /room/v1/Room/playUrl?cid=23371670&otype=json&quality=4&platform=web HTTP/1.1" 200 931 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread BiliLive.py[line:57] DEBUG [Site:BiliBili Room:23371670] 获取到以下地址:https://cn-cq-ct-01-12.bilivideo.com/live-bvc/384431/live_524076304_16608389.flv?expires=1671835902&pt=web&deadline=1671835902&len=0&oi=2883398179&platform=web&qn=10000&trid=1000e50fe69708fb49e4a4fe59fb2bbb263f&uipk=100&uipv=100&nbs=1&uparams=cdn,deadline,len,oi,platform,qn,trid,uipk,uipv,nbs&cdn=cn-gotcha01&upsig=882dcaf36d30fffd165b21c818473261&sk=d7a794fee632e64bb8422fd71c02c0da&p2p_type=0&src=57345&sl=1&free_type=0&sid=cn-cq-ct-01-12&chash=1&sche=ban&score=2&pp=rtmp&source=one&trace=8&site=b05a67226a1517c5a8736d7171ccc4bb&order=1 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread BiliLiveRecorder.py[line:24] INFO [Site:BiliBili Room:23371670] √ 正在录制...23371670 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread connectionpool.py[line:1003] DEBUG Starting new HTTPS connection (1): cn-cq-ct-01-12.bilivideo.com:443 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread connectionpool.py[line:456] DEBUG https://cn-cq-ct-01-12.bilivideo.com:443 "GET /live-bvc/384431/live_524076304_16608389.flv?expires=1671835902&pt=web&deadline=1671835902&len=0&oi=2883398179&platform=web&qn=10000&trid=1000e50fe69708fb49e4a4fe59fb2bbb263f&uipk=100&uipv=100&nbs=1&uparams=cdn,deadline,len,oi,platform,qn,trid,uipk,uipv,nbs&cdn=cn-gotcha01&upsig=882dcaf36d30fffd165b21c818473261&sk=d7a794fee632e64bb8422fd71c02c0da&p2p_type=0&src=57345&sl=1&free_type=0&sid=cn-cq-ct-01-12&chash=1&sche=ban&score=2&pp=rtmp&source=one&trace=8&site=b05a67226a1517c5a8736d7171ccc4bb&order=1 HTTP/1.1" 403 552 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread BiliLiveRecorder.py[line:59] INFO [Site:BiliBili Room:23371670] 录制完成./data/records/23371670_2022-12-24_05-34-16/23371670_2022-12-24_05-50-42.flv Sat, 24 Dec 2022 05:50:42 4603106816 MainThread BaseLive.py[line:84] DEBUG [Site:BiliBili Room:23371670] 间隔不足,使用过去状态 Sat, 24 Dec 2022 05:50:42 4603106816 MainThread connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /room/v1/Room/playUrl?cid=23371670&otype=json&quality=0&platform=web HTTP/1.1" 200 966 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /room/v1/Room/playUrl?cid=23371670&otype=json&quality=4&platform=web HTTP/1.1" 200 931 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread BiliLive.py[line:57] DEBUG [Site:BiliBili Room:23371670] 获取到以下地址:https://cn-cq-ct-01-12.bilivideo.com/live-bvc/635289/live_524076304_16608389.flv?expires=1671835902&pt=web&deadline=1671835902&len=0&oi=2883398179&platform=web&qn=10000&trid=100080c6d741c4a84fbaa1ca9d662df754de&uipk=100&uipv=100&nbs=1&uparams=cdn,deadline,len,oi,platform,qn,trid,uipk,uipv,nbs&cdn=cn-gotcha01&upsig=d3b19bfbc4af5fb49222675c3c53dddc&sk=d7a794fee632e64bb8422fd71c02c0da&p2p_type=0&src=57345&sl=1&free_type=0&sid=cn-cq-ct-01-12&chash=1&sche=ban&score=2&pp=rtmp&source=one&trace=8&site=b05a67226a1517c5a8736d7171ccc4bb&order=1 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread BiliLiveRecorder.py[line:24] INFO [Site:BiliBili Room:23371670] √ 正在录制...23371670 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread connectionpool.py[line:1003] DEBUG Starting new HTTPS connection (1): cn-cq-ct-01-12.bilivideo.com:443 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread connectionpool.py[line:456] DEBUG https://cn-cq-ct-01-12.bilivideo.com:443 "GET /live-bvc/635289/live_524076304_16608389.flv?expires=1671835902&pt=web&deadline=1671835902&len=0&oi=2883398179&platform=web&qn=10000&trid=100080c6d741c4a84fbaa1ca9d662df754de&uipk=100&uipv=100&nbs=1&uparams=cdn,deadline,len,oi,platform,qn,trid,uipk,uipv,nbs&cdn=cn-gotcha01&upsig=d3b19bfbc4af5fb49222675c3c53dddc&sk=d7a794fee632e64bb8422fd71c02c0da&p2p_type=0&src=57345&sl=1&free_type=0&sid=cn-cq-ct-01-12&chash=1&sche=ban&score=2&pp=rtmp&source=one&trace=8&site=b05a67226a1517c5a8736d7171ccc4bb&order=1 HTTP/1.1" 403 552 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread BiliLiveRecorder.py[line:59] INFO [Site:BiliBili Room:23371670] 录制完成./data/records/23371670_2022-12-24_05-34-16/23371670_2022-12-24_05-50-43.flv Sat, 24 Dec 2022 05:50:43 4603106816 MainThread BaseLive.py[line:84] DEBUG [Site:BiliBili Room:23371670] 间隔不足,使用过去状态 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /room/v1/Room/playUrl?cid=23371670&otype=json&quality=0&platform=web HTTP/1.1" 200 966 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread connectionpool.py[line:456] DEBUG https://api.live.bilibili.com:443 "GET /room/v1/Room/playUrl?cid=23371670&otype=json&quality=4&platform=web HTTP/1.1" 200 931 Sat, 24 Dec 2022 05:50:43 4603106816 MainThread BiliLive.py[line:57] DEBUG [Site:BiliBili Room:23371670] 获取到以下地址:https://cn-cq-ct-01-12.bilivideo.com/live-bvc/706611/live_524076304_16608389.flv?expires=1671835903&pt=web&deadline=1671835903&len=0&oi=2883398179&platform=web&qn=10000&trid=1000e4721b45ce884aec8ff7c685c905971d&uipk=100&uipv=100&nbs=1&uparams=cdn,deadline,len,oi,platform,qn,trid,uipk,uipv,nbs&cdn=cn-gotcha01&upsig=dcd837a4d4b42f419453879a61808690&sk=d7a794fee632e64bb8422fd71c02c0da&p2p_type=0&src=57345&sl=1&free_type=0&sid=cn-cq-ct-01-12&chash=1&sche=ban&score=2&pp=rtmp&source=one&trace=8&site=792333886e0f0141a8e22dd611d0366a&order=1

    opened by 0xAmad3us 0
  • bypy报错

    bypy报错

    打包好的exe运行的时候会报以下的错误 Your current version (1.8) is too low, minimum required version is 1.8.1. Please run 'pip install -U bypy' to update and try again.

    opened by Damage0413 0
  • 自动上传稿件失败

    自动上传稿件失败

    日志: Sun, 07 Aug 2022 23:22:09 12484 MainThread connectionpool.py[line:1001] DEBUG Starting new HTTPS connection (1): api.bilibili.com:443 Sun, 07 Aug 2022 23:22:10 12484 MainThread connectionpool.py[line:456] DEBUG https://api.bilibili.com:443 "GET /x/web-interface/nav HTTP/1.1" 200 None Sun, 07 Aug 2022 23:22:10 12484 MainThread connectionpool.py[line:1001] DEBUG Starting new HTTPS connection (1): member.bilibili.com:443 Sun, 07 Aug 2022 23:22:10 12484 MainThread connectionpool.py[line:456] DEBUG https://member.bilibili.com:443 "GET /x/geetest/pre/add HTTP/1.1" 200 114 Sun, 07 Aug 2022 23:22:10 12484 MainThread connectionpool.py[line:228] DEBUG Starting new HTTP connection (1): api.bilibili.com:80 Sun, 07 Aug 2022 23:22:10 12484 MainThread connectionpool.py[line:456] DEBUG http://api.bilibili.com:80 "GET /x/space/myinfo HTTP/1.1" 200 None Sun, 07 Aug 2022 23:22:10 12484 MainThread bili_webup.py[line:481] INFO 用户权重: 1 Sun, 07 Aug 2022 23:22:10 12484 MainThread bili_webup.py[line:504] INFO 使用客户端api端提交 Sun, 07 Aug 2022 23:22:10 12484 MainThread connectionpool.py[line:228] DEBUG Starting new HTTP connection (1): member.bilibili.com:80 Sun, 07 Aug 2022 23:22:10 12484 MainThread connectionpool.py[line:456] DEBUG http://member.bilibili.com:80 "POST /x/vu/client/add?access_key=f2f000a9b504072184d50e014ee75b71 HTTP/1.1" 200 80 Sun, 07 Aug 2022 23:22:10 12484 MainThread Uploader.py[line:140] ERROR [Site:BiliBili Room:11612417] Error while uploading:{'code': 21150, 'message': '投稿入口升级中,请重新编辑稿件', 'ttl': 1}Traceback (most recent call last): File "Uploader.py", line 91, in upload File "biliup\plugins\bili_webup.py", line 496, in submit Exception: {'code': 21150, 'message': '投稿入口升级中,请重新编辑稿件', 'ttl': 1}

    opened by zhuoyanqiu 0
  • 下载1.3.0后提示无法获取DDRecorder的版本信息,当前版本号: {},请到https://github.com/AsaChiri/DDRecorder/releases 检查最新版本'.format(CURRENT_VERSION))

    下载1.3.0后提示无法获取DDRecorder的版本信息,当前版本号: {},请到https://github.com/AsaChiri/DDRecorder/releases 检查最新版本'.format(CURRENT_VERSION))

    Is your feature request related to a problem? Please describe. A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

    Describe the solution you'd like A clear and concise description of what you want to happen.

    Describe alternatives you've considered A clear and concise description of any alternative solutions or features you've considered.

    Additional context Add any other context or screenshots about the feature request here.

    opened by lsnan0209 1
Releases(v1.3.0)
  • v1.3.0(Jul 20, 2022)

    What's Changed

    • 手动切片支持自定义命令 by @JokerQyou in https://github.com/AsaChiri/DDRecorder/pull/65
    • 使用fastHan代替jieba分词
    • 配置项中可以调整上传线路
    • 修正上传分P顺序问题 by @ZhaoWeicheng98 in https://github.com/AsaChiri/DDRecorder/pull/73

    New Contributors

    • @JokerQyou made their first contribution in https://github.com/AsaChiri/DDRecorder/pull/65

    Full Changelog: https://github.com/AsaChiri/DDRecorder/compare/v1.2.3...v1.3.0

    Source code(tar.gz)
    Source code(zip)
    DDRecordert.zip(324.19 MB)
  • v1.2.3(Jan 18, 2021)

    此release包仅可用于Windows x64系统。

    主要更新: DDRecorder:

    1. 自动上传依赖由BilibiliUploader改为biliup,提高稳定性并解决电磁力等级不够无法上传多P稿件的问题。
    2. 修复弹幕记录器被B站弹幕服务器拒绝连接的问题。
    3. 继续尝试修复由于开播状态与实际推流状态不一致导致的包括错误提示、空文件夹等问题。

    此次更新后,使用编辑功能上传多P稿件的功能不再可用。

    DDRecorderConfigManager:

    1. 适配了新的配置文件。
    2. 集成了biliup-rs,可以更方便的获取鉴权信息。

    What's Changed

    • Asachiri/switch-to-biliup by @ZhaoWeicheng98 in https://github.com/AsaChiri/DDRecorder/pull/61
    • fix: live status shadowing by @satouriko in https://github.com/AsaChiri/DDRecorder/pull/58

    Full Changelog: https://github.com/AsaChiri/DDRecorder/compare/v1.2.1...v1.2.3

    Source code(tar.gz)
    Source code(zip)
    DDRecorder.zip(170.54 MB)
  • v1.1.0(Jan 20, 2021)

    此release包仅可用于Windows x64系统。

    主要修改: 1、打包为exe可执行文件并包含了ffmpeg,省去了python和ffmpeg安装步骤,开箱即用。 2、监控多个直播间只需要运行一次,减少内存占用。 3、优化控制台输出,更加明晰。 4、调整了多进程模型,对一些进程进行了合并。 DDRecorder 5、bug修复

    Source code(tar.gz)
    Source code(zip)
    DDRecorder.zip(144.22 MB)
  • v1.0.3(Jan 18, 2021)

Owner
null