diff --git a/v6d3music/ffmpegtoraudio.py b/v6d3music/ffmpegnormalaudio.py similarity index 60% rename from v6d3music/ffmpegtoraudio.py rename to v6d3music/ffmpegnormalaudio.py index 005ad5f..7beefb5 100644 --- a/v6d3music/ffmpegtoraudio.py +++ b/v6d3music/ffmpegnormalaudio.py @@ -1,12 +1,20 @@ import shlex import subprocess +import time import discord -class FFmpegTorAudio(discord.FFmpegAudio): - def __init__(self, source, *, executable='ffmpeg', pipe=False, stderr=None, before_options=None, options=None): - args = [executable] +class FFmpegNormalAudio(discord.FFmpegAudio): + def __init__( + self, source, *, executable='ffmpeg', pipe=False, stderr=None, before_options=None, options=None, + tor: bool + ): + args = [] + if tor: + args.append(executable) + executable = 'torify' + subprocess_kwargs = {'stdin': source if pipe else subprocess.DEVNULL, 'stderr': stderr} if isinstance(before_options, str): @@ -21,11 +29,13 @@ class FFmpegTorAudio(discord.FFmpegAudio): args.append('pipe:1') - super().__init__(source, executable='torify', args=args, **subprocess_kwargs) + super().__init__(source, executable=executable, args=args, **subprocess_kwargs) def read(self): ret = self._stdout.read(discord.opus.Encoder.FRAME_SIZE) if len(ret) != discord.opus.Encoder.FRAME_SIZE: + if self._process.poll() is None: + time.sleep(.5) return b'' return ret diff --git a/v6d3music/run-bot.py b/v6d3music/run-bot.py index 33b2b61..282940c 100644 --- a/v6d3music/run-bot.py +++ b/v6d3music/run-bot.py @@ -23,7 +23,7 @@ from v6d2ctx.lock_for import lock_for from v6d2ctx.serve import serve import v6d3music.extract -import v6d3music.ffmpegtoraudio +import v6d3music.ffmpegnormalaudio from v6d3music.config import prefix, myroot loop = asyncio.new_event_loop() @@ -146,13 +146,11 @@ class YTAudio(discord.AudioSource): def set_source(self): self.schedule_duration_update() - audio_class = discord.FFmpegPCMAudio - if self.tor: - audio_class = v6d3music.ffmpegtoraudio.FFmpegTorAudio - self.source = audio_class( + self.source = v6d3music.ffmpegnormalaudio.FFmpegNormalAudio( self.url, options=self.options, - before_options=self.before_options() + before_options=self.before_options(), + tor=self.tor ) def set_already_read(self, already_read: int): @@ -456,6 +454,7 @@ async def cache_url(hurl: str, rurl: str, override: bool, tor: bool) -> None: if cachable: print('caching', hurl) path = cache_root / f'{hurl}.opus' + tmp_path = cache_root / f'{hurl}.tmp.opus' args = [] if tor: args.append('torify') @@ -464,7 +463,7 @@ async def cache_url(hurl: str, rurl: str, override: bool, tor: bool) -> None: 'ffmpeg', '-hide_banner', '-loglevel', 'warning', '-reconnect', '1', '-reconnect_at_eof', '0', '-reconnect_streamed', '1', '-reconnect_delay_max', '10', '-copy_unknown', - '-y', '-i', rurl, str(path) + '-y', '-i', rurl, str(tmp_path) ] ) p = subprocess.Popen( @@ -474,6 +473,7 @@ async def cache_url(hurl: str, rurl: str, override: bool, tor: bool) -> None: code = await loop.run_in_executor(None, p.wait) if code: raise RuntimeError(code) + await loop.run_in_executor(None, tmp_path.rename, path) await cache_db.set(f'url:{hurl}', str(path)) print('cached', hurl) # await cache_db.set(f'cachable:{hurl}', False) @@ -578,11 +578,12 @@ presets: dict[str, str] = { 'bassboost': 'bass=g=10', 'bassbooboost': 'bass=g=30', 'nightcore': 'asetrate=67882', + 'daycore': 'atempo=.9,aecho=1.0:0.5:20:0.5', 'пришествие анимешне': 'bass=g=15,asetrate=67882,bass=g=15', 'difference': 'aeval=val(0)-val(1)|val(1)-val(0)', 'mono': 'aeval=.5*val(0)+.5*val(1)|.5*val(1)+.5*val(0)', } -allowed_presets = ['bassboost', 'bassbooboost', 'nightcore', 'mono'] +allowed_presets = ['bassboost', 'bassbooboost', 'nightcore', 'daycore', 'mono'] allowed_effects = {'', *(presets[key] for key in allowed_presets)}