mirror of
https://github.com/acgnhiki/blrec.git
synced 2025-01-14 04:10:06 +08:00
release: 1.2.3
This commit is contained in:
parent
36f09499af
commit
047c098271
@ -1,5 +1,10 @@
|
||||
# 更新日志
|
||||
|
||||
## 1.2.3
|
||||
|
||||
- 修复直播间标题有特殊字符导致文件创建失败
|
||||
- 修复弹幕有特殊字符导致弹幕录制出错
|
||||
|
||||
## 1.2.2
|
||||
|
||||
- 避免 url 失效出现一直超时不能录制
|
||||
|
48
setup.cfg
48
setup.cfg
@ -36,41 +36,41 @@ include_package_data = True
|
||||
python_requires = >= 3.8
|
||||
install_requires =
|
||||
typing-extensions >= 3.10.0.0
|
||||
fastapi >= 0.65.2, < 0.66.0
|
||||
email_validator >=1.1.2, < 2.0.0
|
||||
typer >= 0.3.2, < 0.4.0
|
||||
aiohttp >= 3.6.2, < 3.7.0
|
||||
requests >= 2.24.0, < 2.25.0
|
||||
aiofiles >= 0.5.0, < 0.6.0
|
||||
tenacity >= 6.2.0, < 6.3.0
|
||||
colorama >= 0.4.3, < 0.5.0
|
||||
humanize >= 3.2.0, < 3.3.0
|
||||
tqdm >= 4.56.2, < 4.57.0
|
||||
attrs >= 21.2.0, < 21.3.0
|
||||
lxml >= 4.6.2, < 4.7.0
|
||||
fastapi >= 0.70.0, < 0.71.0
|
||||
email_validator >= 1.1.3, < 2.0.0
|
||||
typer >= 0.4.0, < 0.5.0
|
||||
aiohttp >= 3.8.1, < 4.0.0
|
||||
requests >= 2.24.0, < 3.0.0
|
||||
aiofiles >= 0.8.0, < 0.9.0
|
||||
tenacity >= 8.0.1, < 9.0.0
|
||||
colorama >= 0.4.4, < 0.5.0
|
||||
humanize >= 3.13.1, < 4.0.0
|
||||
tqdm >= 4.62.3, < 5.0.0
|
||||
attrs >= 21.2.0, < 22.0.0
|
||||
lxml >= 4.6.4, < 5.0.0
|
||||
toml >= 0.10.2, < 0.11.0
|
||||
psutil >= 5.8.0, < 5.9.0
|
||||
rx >= 3.1.1, < 3.2.0
|
||||
bitarray >= 2.2.5, < 2.3.0
|
||||
brotli >= 1.0.9, < 1.1.0
|
||||
uvicorn[standard] >=0.12.0, < 0.15.0
|
||||
psutil >= 5.8.0, < 6.0.0
|
||||
rx >= 3.2.0, < 4.0.0
|
||||
bitarray >= 2.2.5, < 3.0.0
|
||||
brotli >= 1.0.9, < 2.0.0
|
||||
uvicorn[standard] >= 0.15.0, < 0.16.0
|
||||
|
||||
[options.extras_require]
|
||||
dev =
|
||||
flake8 >= 3.9.2, < 4.0.0
|
||||
flake8 >= 4.0.1, < 5.0.0
|
||||
mypy >= 0.910, < 1.000
|
||||
|
||||
setuptools >= 57.0.0, < 58.0.0
|
||||
setuptools >= 59.4.0, < 60.0.0
|
||||
wheel >= 0.37, < 0.38.0
|
||||
build >= 0.5.1, < 0.6.0
|
||||
build >= 0.7.0, < 0.8.0
|
||||
|
||||
# missing stub packages
|
||||
types-requests >= 2.25.1, < 2.26.0
|
||||
types-requests >= 2.26.1, < 3.0.0
|
||||
types-aiofiles >= 0.1.7, < 0.2.0
|
||||
types-toml >= 0.1.3, < 0.2.0
|
||||
types-setuptools >= 57.0.0, < 58.0.0
|
||||
types-toml >= 0.10.1, < 0.11.0
|
||||
types-setuptools >= 57.4.4, < 58.0.0
|
||||
|
||||
speedups = aiohttp[speedups] >= 3.6.2, < 3.7.0
|
||||
speedups = aiohttp[speedups] >= 3.8.1, < 4.0.0
|
||||
|
||||
[options.packages.find]
|
||||
where = src
|
||||
|
@ -1,4 +1,4 @@
|
||||
|
||||
__prog__ = 'blrec'
|
||||
__version__ = '1.2.2'
|
||||
__version__ = '1.2.3'
|
||||
__github__ = 'https://github.com/acgnhiki/blrec'
|
||||
|
@ -3,7 +3,6 @@ from typing import Any, Callable, Optional, Type, cast
|
||||
|
||||
from tenacity import wait_exponential, RetryCallState
|
||||
from tenacity import _utils
|
||||
from tenacity import compat as _compat
|
||||
|
||||
|
||||
class wait_exponential_for_same_exceptions(wait_exponential):
|
||||
@ -25,7 +24,6 @@ class wait_exponential_for_same_exceptions(wait_exponential):
|
||||
self._prev_exc_ts: Optional[float] = None
|
||||
self._last_wait_time: float = 0
|
||||
|
||||
@_compat.wait_dunder_call_accept_old_params
|
||||
def __call__(self, retry_state: RetryCallState) -> float:
|
||||
if (
|
||||
retry_state.outcome is not None and
|
||||
|
@ -39,6 +39,7 @@ from ..bili.live import Live
|
||||
from ..bili.typing import QualityNumber
|
||||
from ..flv.stream_processor import StreamProcessor, BaseOutputFileManager
|
||||
from ..utils.mixins import AsyncCooperationMix, AsyncStoppableMixin
|
||||
from ..path import escape_path
|
||||
from ..flv.exceptions import FlvStreamCorruptedError
|
||||
from ..bili.exceptions import (
|
||||
LiveRoomHidden, LiveRoomLocked, LiveRoomEncrypted, NoStreamUrlAvailable
|
||||
@ -501,10 +502,10 @@ class OutputFileManager(BaseOutputFileManager, AsyncCooperationMix):
|
||||
date_time = datetime.fromtimestamp(self._start_time)
|
||||
relpath = self.path_template.format(
|
||||
roomid=self._live.room_id,
|
||||
uname=self._live.user_info.name,
|
||||
title=self._live.room_info.title,
|
||||
area=self._live.room_info.area_name,
|
||||
parent_area=self._live.room_info.parent_area_name,
|
||||
uname=escape_path(self._live.user_info.name),
|
||||
title=escape_path(self._live.room_info.title),
|
||||
area=escape_path(self._live.room_info.area_name),
|
||||
parent_area=escape_path(self._live.room_info.parent_area_name),
|
||||
year=date_time.year,
|
||||
month=str(date_time.month).rjust(2, '0'),
|
||||
day=str(date_time.day).rjust(2, '0'),
|
||||
|
@ -1,6 +1,8 @@
|
||||
from __future__ import annotations
|
||||
import html
|
||||
import asyncio
|
||||
import logging
|
||||
import unicodedata
|
||||
from typing import AsyncIterator, Final, List, Any
|
||||
|
||||
from lxml import etree
|
||||
@ -16,6 +18,9 @@ from .models import (
|
||||
__all__ = 'DanmakuReader', 'DanmakuWriter'
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class DanmakuReader: # TODO rewrite
|
||||
def __init__(self, path: str) -> None:
|
||||
self._path = path
|
||||
@ -146,7 +151,12 @@ class DanmakuWriter:
|
||||
'user': dm.uname,
|
||||
}
|
||||
elem = etree.Element('d', attrib=attrib)
|
||||
elem.text = dm.text
|
||||
try:
|
||||
elem.text = dm.text
|
||||
except ValueError:
|
||||
# ValueError: All strings must be XML compatible: Unicode or ASCII,
|
||||
# no NULL bytes or control characters
|
||||
elem.text = remove_control_characters(dm.text)
|
||||
return ' ' + etree.tostring(elem, encoding='utf8').decode() + '\n'
|
||||
|
||||
def _serialize_gift_send_record(self, record: GiftSendRecord) -> str:
|
||||
@ -166,7 +176,10 @@ class DanmakuWriter:
|
||||
value_serializer=record_value_serializer,
|
||||
)
|
||||
elem = etree.Element('sc', attrib=attrib)
|
||||
elem.text = record.message
|
||||
try:
|
||||
elem.text = record.message
|
||||
except ValueError:
|
||||
elem.text = remove_control_characters(record.message)
|
||||
return ' ' + etree.tostring(elem, encoding='utf8').decode() + '\n'
|
||||
|
||||
|
||||
@ -180,3 +193,7 @@ def record_value_serializer(
|
||||
if not isinstance(value, str):
|
||||
return str(value)
|
||||
return value
|
||||
|
||||
|
||||
def remove_control_characters(s: str) -> str:
|
||||
return ''.join(c for c in s if unicodedata.category(c) != 'Cc')
|
||||
|
@ -4,6 +4,7 @@ from .helpers import (
|
||||
danmaku_path,
|
||||
raw_danmaku_path,
|
||||
extra_metadata_path,
|
||||
escape_path,
|
||||
)
|
||||
|
||||
|
||||
@ -13,4 +14,5 @@ __all__ = (
|
||||
'danmaku_path',
|
||||
'raw_danmaku_path',
|
||||
'extra_metadata_path',
|
||||
'escape_path',
|
||||
)
|
||||
|
@ -1,3 +1,4 @@
|
||||
import re
|
||||
import os
|
||||
from pathlib import PurePath
|
||||
|
||||
@ -8,6 +9,7 @@ __all__ = (
|
||||
'danmaku_path',
|
||||
'raw_danmaku_path',
|
||||
'extra_metadata_path',
|
||||
'escape_path',
|
||||
)
|
||||
|
||||
|
||||
@ -31,3 +33,7 @@ def raw_danmaku_path(video_path: str) -> str:
|
||||
|
||||
def extra_metadata_path(video_path: str) -> str:
|
||||
return video_path + '.meta.json'
|
||||
|
||||
|
||||
def escape_path(path: str) -> str:
|
||||
return re.sub(r'[\\/:*?"<>|]', '', path)
|
||||
|
Loading…
Reference in New Issue
Block a user