release: v1.0.5

This commit is contained in:
acgnhiki 2021-09-18 13:52:12 +08:00
parent 4f1d6bef27
commit 6b61738d09
14 changed files with 70 additions and 24 deletions

View File

@ -1,5 +1,11 @@
# 更新日志
## 1.0.5
- 修复路径模板设置的模板变量显示不完整
- 修复主机绑定不是 localhost 自动打开浏览器访问出错
- 其它一些重构调整
## 1.0.4
- 兼容 SRT 推流

View File

@ -1,3 +1,4 @@
__version__ = '1.0.4'
__prog__ = 'blrec'
__version__ = '1.0.5'
__github__ = 'https://github.com/acgnhiki/blrec'

View File

@ -5,6 +5,13 @@ import json
from typing import Dict, List, Optional, cast
import aiohttp
from tenacity import (
retry,
wait_exponential,
stop_after_delay,
retry_if_exception_type,
)
from .api import WebApi
from .models import LiveStatus, RoomInfo, UserInfo
@ -32,6 +39,9 @@ class Live:
self._cookie = cookie
self._html_page_url = f'https://live.bilibili.com/{room_id}'
self._room_info: RoomInfo
self._user_info: UserInfo
@property
def user_agent(self) -> str:
return self._user_agent
@ -103,9 +113,25 @@ class Live:
async def update_info(self) -> None:
await asyncio.wait([self.update_user_info(), self.update_room_info()])
@retry(
reraise=True,
retry=retry_if_exception_type((
asyncio.TimeoutError, aiohttp.ClientError,
)),
wait=wait_exponential(max=10),
stop=stop_after_delay(60),
)
async def update_user_info(self) -> None:
self._user_info = await self.get_user_info(self._room_info.uid)
@retry(
reraise=True,
retry=retry_if_exception_type((
asyncio.TimeoutError, aiohttp.ClientError,
)),
wait=wait_exponential(max=10),
stop=stop_after_delay(60),
)
async def update_room_info(self) -> None:
self._room_info = await self.get_room_info()

View File

@ -103,7 +103,11 @@ class LiveMonitor(
))
await self._live.update_info()
assert self._live.room_info.live_status == current_status
if (s := self._live.room_info.live_status) != current_status:
logger.warning(
'Updated live status {} is inconsistent with '
'current live status {}'.format(s.name, current_status.name)
)
await self._emit(
'live_status_changed', current_status, self._previous_status

View File

@ -44,7 +44,7 @@ def cli_main(
'-o',
help='path of directory to save files (overwrite setting)'
),
host: str = typer.Option('127.0.0.1', help='webapp host bind'),
host: str = typer.Option('localhost', help='webapp host bind'),
port: int = typer.Option(2233, help='webapp port bind'),
open: bool = typer.Option(False, help='open webapp in default browser'),
key_file: Optional[str] = typer.Option(None, help='SSL key file'),
@ -60,7 +60,7 @@ def cli_main(
os.environ['out_dir'] = out_dir
if open:
typer.launch(f'http://{host}:{port}')
typer.launch(f'http://localhost:{port}')
logging_config = deepcopy(LOGGING_CONFIG)
logging_config['handlers']['default']['stream'] = TqdmOutputStream

View File

@ -5,7 +5,7 @@ from contextlib import suppress
from typing import Iterator, List
from .. import __version__, __prog__
from .. import __version__, __prog__, __github__
from .danmaku_receiver import DanmakuReceiver, DanmuMsg
from .stream_recorder import StreamRecorder, StreamRecorderEventListener
from .statistics import StatisticsCalculator
@ -131,7 +131,7 @@ class DanmakuDumper(StreamRecorderEventListener, SwitchableMixin):
parent_area=self._live.room_info.parent_area_name,
live_start_time=self._live.room_info.live_start_time,
record_start_time=self._record_start_time,
recorder=f'{__prog__} {__version__}',
recorder=f'{__prog__} v{__version__} {__github__}',
)
def _make_danmu(self, msg: DanmuMsg) -> Danmu:

View File

@ -31,7 +31,7 @@ from tenacity import (
TryAgain,
)
from .. import __version__, __prog__
from .. import __version__, __prog__, __github__
from .retry import wait_exponential_for_same_exceptions, before_sleep_log
from .statistics import StatisticsCalculator
from ..event.event_emitter import EventListener, EventEmitter
@ -365,7 +365,6 @@ class StreamRecorder(
)
def _make_metadata(self) -> Dict[str, Any]:
github_url = 'https://github.com/acgnhiki/blrec'
live_start_time = datetime.fromtimestamp(
self._live.room_info.live_start_time, timezone(timedelta(hours=8))
)
@ -381,7 +380,7 @@ B站直播录像
分区{self._live.room_info.parent_area_name} - {self._live.room_info.area_name}
房间号{self._live.room_info.room_id}
开播时间{live_start_time}
录制程序{__prog__} v{__version__} {github_url}''',
录制程序{__prog__} v{__version__} {__github__}''',
'description': OrderedDict({
'UserId': str(self._live.user_info.uid),
'UserName': self._live.user_info.name,
@ -390,7 +389,7 @@ B站直播录像
'Area': self._live.room_info.area_name,
'ParentArea': self._live.room_info.parent_area_name,
'LiveStartTime': str(live_start_time),
'Recorder': f'{__prog__} v{__version__} {github_url}',
'Recorder': f'{__prog__} v{__version__} {__github__}',
})
}

View File

@ -10,6 +10,6 @@
<body>
<app-root></app-root>
<noscript>Please enable JavaScript to continue using this application.</noscript>
<script src="runtime.9c55e9c0a6d0459b5e96.js" defer></script><script src="polyfills.a427f031f0f7196ffda1.js" defer></script><script src="main.22f06d53efe81d9df3a8.js" defer></script>
<script src="runtime.4c79c38349615627b59b.js" defer></script><script src="polyfills.a427f031f0f7196ffda1.js" defer></script><script src="main.22f06d53efe81d9df3a8.js" defer></script>
</body></html>

View File

@ -1,6 +1,6 @@
{
"configVersion": 1,
"timestamp": 1628613033243,
"timestamp": 1631943201826,
"index": "/index.html",
"assetGroups": [
{
@ -12,7 +12,7 @@
},
"urls": [
"/198.20d927ba29c55516dd2e.js",
"/51.560338ef5c3689b822f9.js",
"/51.275a97b45765f0cf1623.js",
"/659.4923e830b3feb2abcce2.js",
"/80.78cb9b41766e5c57d657.js",
"/954.05cbcc74da25eb3ef2a9.js",
@ -21,7 +21,7 @@
"/main.22f06d53efe81d9df3a8.js",
"/manifest.webmanifest",
"/polyfills.a427f031f0f7196ffda1.js",
"/runtime.9c55e9c0a6d0459b5e96.js",
"/runtime.4c79c38349615627b59b.js",
"/styles.09c5ed83b6748436b293.css"
],
"patterns": []
@ -1632,7 +1632,7 @@
"dataGroups": [],
"hashTable": {
"/198.20d927ba29c55516dd2e.js": "93bf87b6cc89e0a67c508c5c232d50d73c659057",
"/51.560338ef5c3689b822f9.js": "c31964ceca4ec203c3a60de2e75667ac4bfd5528",
"/51.275a97b45765f0cf1623.js": "0bcd069e622a8682773ea72e425c191b391509cb",
"/659.4923e830b3feb2abcce2.js": "e74b2b9b53cd108ab7e91f765ca0926c42b3fd1f",
"/80.78cb9b41766e5c57d657.js": "ae52bd0e9cf819763e1f843ead3fb5adc10afffa",
"/954.05cbcc74da25eb3ef2a9.js": "38c071c377d3a6d98902e679340d6a609996b717",
@ -3228,11 +3228,11 @@
"/assets/twotone/warning.js": "fb2d7ea232f3a99bf8f080dbc94c65699232ac01",
"/assets/twotone/warning.svg": "8c7a2d3e765a2e7dd58ac674870c6655cecb0068",
"/common.fa68e1b34f0baff6ccad.js": "8e62b9aa49dde6486f74c6c94b97054743f1cc1b",
"/index.html": "cdd5b6a2184b9d03b7afeea5e2721c4c63d6772a",
"/index.html": "98bb17017bf0130fb96ffae491a76787731b918c",
"/main.22f06d53efe81d9df3a8.js": "edb0ba67f76a4a734eaf210655790ca4926f45a6",
"/manifest.webmanifest": "0c4534b4c868d756691b1b4372cecb2efce47c6d",
"/polyfills.a427f031f0f7196ffda1.js": "3e4560be48cd30e30bcbf51ca131a37d8c224fdc",
"/runtime.9c55e9c0a6d0459b5e96.js": "514cd785b41aa8c04d9925e4b5313d48d7404612",
"/runtime.4c79c38349615627b59b.js": "f6de29446d188dd27541769e856ced4fa651e670",
"/styles.09c5ed83b6748436b293.css": "c08136817a63dadd53de8cb2df2d56ba95e5905a"
},
"navigationUrls": [

View File

@ -1 +1 @@
(()=>{"use strict";var e,v={},m={};function r(e){var n=m[e];if(void 0!==n)return n.exports;var t=m[e]={exports:{}};return v[e].call(t.exports,t,t.exports,r),t.exports}r.m=v,e=[],r.O=(n,t,i,o)=>{if(!t){var a=1/0;for(f=0;f<e.length;f++){for(var[t,i,o]=e[f],d=!0,l=0;l<t.length;l++)(!1&o||a>=o)&&Object.keys(r.O).every(p=>r.O[p](t[l]))?t.splice(l--,1):(d=!1,o<a&&(a=o));if(d){e.splice(f--,1);var c=i();void 0!==c&&(n=c)}}return n}o=o||0;for(var f=e.length;f>0&&e[f-1][2]>o;f--)e[f]=e[f-1];e[f]=[t,i,o]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>(592===e?"common":e)+"."+{51:"560338ef5c3689b822f9",80:"78cb9b41766e5c57d657",198:"20d927ba29c55516dd2e",592:"fa68e1b34f0baff6ccad",659:"4923e830b3feb2abcce2",954:"05cbcc74da25eb3ef2a9"}[e]+".js",r.miniCssF=e=>"styles.09c5ed83b6748436b293.css",r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="blrec:";r.l=(t,i,o,f)=>{if(e[t])e[t].push(i);else{var a,d;if(void 0!==o)for(var l=document.getElementsByTagName("script"),c=0;c<l.length;c++){var u=l[c];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==n+o){a=u;break}}a||(d=!0,(a=document.createElement("script")).charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+o),a.src=r.tu(t)),e[t]=[i];var s=(g,p)=>{a.onerror=a.onload=null,clearTimeout(b);var _=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),_&&_.forEach(h=>h(p)),g)return g(p)},b=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),d&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;r.tu=n=>(void 0===e&&(e={createScriptURL:t=>t},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e.createScriptURL(n))})(),r.p="",(()=>{var e={666:0};r.f.j=(i,o)=>{var f=r.o(e,i)?e[i]:void 0;if(0!==f)if(f)o.push(f[2]);else if(666!=i){var a=new Promise((u,s)=>f=e[i]=[u,s]);o.push(f[2]=a);var d=r.p+r.u(i),l=new Error;r.l(d,u=>{if(r.o(e,i)&&(0!==(f=e[i])&&(e[i]=void 0),f)){var s=u&&("load"===u.type?"missing":u.type),b=u&&u.target&&u.target.src;l.message="Loading chunk "+i+" failed.\n("+s+": "+b+")",l.name="ChunkLoadError",l.type=s,l.request=b,f[1](l)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var n=(i,o)=>{var l,c,[f,a,d]=o,u=0;for(l in a)r.o(a,l)&&(r.m[l]=a[l]);if(d)var s=d(r);for(i&&i(o);u<f.length;u++)r.o(e,c=f[u])&&e[c]&&e[c][0](),e[f[u]]=0;return r.O(s)},t=self.webpackChunkblrec=self.webpackChunkblrec||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();
(()=>{"use strict";var e,v={},m={};function r(e){var n=m[e];if(void 0!==n)return n.exports;var t=m[e]={exports:{}};return v[e].call(t.exports,t,t.exports,r),t.exports}r.m=v,e=[],r.O=(n,t,i,o)=>{if(!t){var a=1/0;for(f=0;f<e.length;f++){for(var[t,i,o]=e[f],d=!0,l=0;l<t.length;l++)(!1&o||a>=o)&&Object.keys(r.O).every(p=>r.O[p](t[l]))?t.splice(l--,1):(d=!1,o<a&&(a=o));if(d){e.splice(f--,1);var c=i();void 0!==c&&(n=c)}}return n}o=o||0;for(var f=e.length;f>0&&e[f-1][2]>o;f--)e[f]=e[f-1];e[f]=[t,i,o]},r.n=e=>{var n=e&&e.__esModule?()=>e.default:()=>e;return r.d(n,{a:n}),n},r.d=(e,n)=>{for(var t in n)r.o(n,t)&&!r.o(e,t)&&Object.defineProperty(e,t,{enumerable:!0,get:n[t]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((n,t)=>(r.f[t](e,n),n),[])),r.u=e=>(592===e?"common":e)+"."+{51:"275a97b45765f0cf1623",80:"78cb9b41766e5c57d657",198:"20d927ba29c55516dd2e",592:"fa68e1b34f0baff6ccad",659:"4923e830b3feb2abcce2",954:"05cbcc74da25eb3ef2a9"}[e]+".js",r.miniCssF=e=>"styles.09c5ed83b6748436b293.css",r.o=(e,n)=>Object.prototype.hasOwnProperty.call(e,n),(()=>{var e={},n="blrec:";r.l=(t,i,o,f)=>{if(e[t])e[t].push(i);else{var a,d;if(void 0!==o)for(var l=document.getElementsByTagName("script"),c=0;c<l.length;c++){var u=l[c];if(u.getAttribute("src")==t||u.getAttribute("data-webpack")==n+o){a=u;break}}a||(d=!0,(a=document.createElement("script")).charset="utf-8",a.timeout=120,r.nc&&a.setAttribute("nonce",r.nc),a.setAttribute("data-webpack",n+o),a.src=r.tu(t)),e[t]=[i];var s=(g,p)=>{a.onerror=a.onload=null,clearTimeout(b);var _=e[t];if(delete e[t],a.parentNode&&a.parentNode.removeChild(a),_&&_.forEach(h=>h(p)),g)return g(p)},b=setTimeout(s.bind(null,void 0,{type:"timeout",target:a}),12e4);a.onerror=s.bind(null,a.onerror),a.onload=s.bind(null,a.onload),d&&document.head.appendChild(a)}}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;r.tu=n=>(void 0===e&&(e={createScriptURL:t=>t},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("angular#bundler",e))),e.createScriptURL(n))})(),r.p="",(()=>{var e={666:0};r.f.j=(i,o)=>{var f=r.o(e,i)?e[i]:void 0;if(0!==f)if(f)o.push(f[2]);else if(666!=i){var a=new Promise((u,s)=>f=e[i]=[u,s]);o.push(f[2]=a);var d=r.p+r.u(i),l=new Error;r.l(d,u=>{if(r.o(e,i)&&(0!==(f=e[i])&&(e[i]=void 0),f)){var s=u&&("load"===u.type?"missing":u.type),b=u&&u.target&&u.target.src;l.message="Loading chunk "+i+" failed.\n("+s+": "+b+")",l.name="ChunkLoadError",l.type=s,l.request=b,f[1](l)}},"chunk-"+i,i)}else e[i]=0},r.O.j=i=>0===e[i];var n=(i,o)=>{var l,c,[f,a,d]=o,u=0;for(l in a)r.o(a,l)&&(r.m[l]=a[l]);if(d)var s=d(r);for(i&&i(o);u<f.length;u++)r.o(e,c=f[u])&&e[c]&&e[c][0](),e[f[u]]=0;return r.O(s)},t=self.webpackChunkblrec=self.webpackChunkblrec||[];t.forEach(n.bind(null,0)),t.push=n.bind(null,t.push.bind(t))})()})();

View File

@ -129,10 +129,15 @@ def is_metadata_tag(tag: FlvTag) -> TypeGuard[ScriptTag]:
def is_data_tag(tag: FlvTag) -> TypeGuard[Union[AudioTag, VideoTag]]:
return (
(is_video_tag(tag) and tag.is_avc_nalu()) or
(is_audio_tag(tag) and tag.is_aac_raw())
)
return is_audio_data_tag(tag) or is_video_data_tag(tag)
def is_audio_data_tag(tag: FlvTag) -> TypeGuard[AudioTag]:
return is_audio_tag(tag) and tag.is_aac_raw()
def is_video_data_tag(tag: FlvTag) -> TypeGuard[VideoTag]:
return is_video_tag(tag) and tag.is_avc_nalu()
def is_sequence_header(tag: FlvTag) -> TypeGuard[Union[AudioTag, VideoTag]]:

View File

@ -687,11 +687,15 @@ class FlvReaderWithTimestampFix(FlvReader):
self._update_parameters(tag)
return tag
if not is_data_tag(tag):
return tag
if self._is_ts_rebounded(tag):
self._update_delta(tag)
logger.warning(
f'Timestamp rebounded, updated delta: {self._delta}\n'
f'last tag: {self._last_tag}\n'
f'last video tag: {self._last_video_tag}\n'
f'last audio tag: {self._last_audio_tag}\n'
f'current tag: {tag}'
)

View File

@ -30,6 +30,7 @@
<nz-table
#table
[nzData]="pathTemplateVariables"
[nzPageSize]="11"
[nzShowPagination]="false"
[nzSize]="'small'"
>