Compare commits
2 commits
wip/modque
...
main
Author | SHA1 | Date | |
---|---|---|---|
2d908e60a5 | |||
d53508c158 |
5 changed files with 3 additions and 180 deletions
|
@ -53,7 +53,7 @@ class Clip:
|
||||||
|
|
||||||
def stretch(self, speed, keep_pitch=True):
|
def stretch(self, speed, keep_pitch=True):
|
||||||
if keep_pitch:
|
if keep_pitch:
|
||||||
stretched = tsm.wsola(self._stereo_transpose(self.raw), speed)
|
stretched = tsm.wsola(self._stereo_transpose(self.raw), 1 / speed)
|
||||||
else:
|
else:
|
||||||
stretched = librosa.resample(self._stereo_transpose(self.raw), self.samplerate * speed, self.samplerate, fix=False, scale=True)
|
stretched = librosa.resample(self._stereo_transpose(self.raw), self.samplerate * speed, self.samplerate, fix=False, scale=True)
|
||||||
self.raw = np.ascontiguousarray(self._stereo_transpose(stretched), dtype='float32')
|
self.raw = np.ascontiguousarray(self._stereo_transpose(stretched), dtype='float32')
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
from .mod import ModPlugin as Plugin
|
|
|
@ -1,103 +0,0 @@
|
||||||
from dataclasses import dataclass, field, asdict
|
|
||||||
from enum import Enum
|
|
||||||
import asyncio
|
|
||||||
from typing import Callable
|
|
||||||
import quart
|
|
||||||
import json
|
|
||||||
import random
|
|
||||||
|
|
||||||
import kdl
|
|
||||||
|
|
||||||
from ovtk_audiencekit.core import PluginBase
|
|
||||||
from ovtk_audiencekit.utils import format_exception
|
|
||||||
from ovtk_audiencekit.events.Message import SysMessage
|
|
||||||
|
|
||||||
|
|
||||||
class Judgement(Enum):
|
|
||||||
cringe = 0
|
|
||||||
based = 1
|
|
||||||
|
|
||||||
@dataclass
|
|
||||||
class Item:
|
|
||||||
id: int = field(init=False)
|
|
||||||
links: list[str]
|
|
||||||
files: list[str]
|
|
||||||
kdl: list[str]
|
|
||||||
ctx: dict
|
|
||||||
user: str = None
|
|
||||||
judgement: Judgement = None
|
|
||||||
|
|
||||||
def __post_init__(self):
|
|
||||||
self.id = random.getrandbits(32)
|
|
||||||
|
|
||||||
def describe(self):
|
|
||||||
return asdict(self)
|
|
||||||
|
|
||||||
|
|
||||||
class ModPlugin(PluginBase):
|
|
||||||
def setup(self):
|
|
||||||
self.requests = {}
|
|
||||||
self._queue_change_ev = asyncio.Event()
|
|
||||||
|
|
||||||
self.blueprint.add_url_rule('/', 'ctrlpanel', self.ui_ctrlpanel)
|
|
||||||
self.blueprint.add_url_rule('/<id>/<is_based>', 'api-review', self.ui_review)
|
|
||||||
self.blueprint.add_url_rule('/monitor', 'monitor', self.ui_monitor_ws, is_websocket=True)
|
|
||||||
|
|
||||||
async def run(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
async def send(self, _children=None, _ctx={}):
|
|
||||||
user = None
|
|
||||||
if source_ev := _ctx.get('event'):
|
|
||||||
if 'user_name' in source_ev.__dict__:
|
|
||||||
user = source_ev.user_name
|
|
||||||
|
|
||||||
item = Item(_children, _ctx, user)
|
|
||||||
self.requests[item.id] = item
|
|
||||||
self._queue_change_ev.set()
|
|
||||||
|
|
||||||
async def review(self, selector, judgement, _ctx={}):
|
|
||||||
if selector == 'last':
|
|
||||||
item_id = self.requests.keys()[-1]
|
|
||||||
item = self.requests[item_id]
|
|
||||||
else:
|
|
||||||
item = self.requests.get(selector)
|
|
||||||
|
|
||||||
if item is None:
|
|
||||||
if source := _ctx.get('event'):
|
|
||||||
msg = SysMessage(self._name, f"No item found", replies_to=source)
|
|
||||||
self.chats[source.via].send(msg)
|
|
||||||
return
|
|
||||||
|
|
||||||
item.judgement = Judgement(int(is_based))
|
|
||||||
self._queue_change_ev.set()
|
|
||||||
|
|
||||||
async def _runner_loop(self):
|
|
||||||
while True:
|
|
||||||
await self._queue_change_ev.wait()
|
|
||||||
for id, item in requests.items():
|
|
||||||
if item.judgement is not None:
|
|
||||||
await self.execute_kdl(item.kdl, _ctx=item.ctx)
|
|
||||||
|
|
||||||
async def ui_ctrlpanel(self):
|
|
||||||
groups = self._ui_get_state()
|
|
||||||
return await self.blueprint.render('index.html', init_state=json.dumps(groups))
|
|
||||||
|
|
||||||
async def ui_review(self, id=None):
|
|
||||||
data = await request.get_data()
|
|
||||||
self.judge(id, is_based)
|
|
||||||
return quart.Response(status=200)
|
|
||||||
|
|
||||||
async def ui_monitor_ws(self):
|
|
||||||
await quart.websocket.accept()
|
|
||||||
while True:
|
|
||||||
groups = self._ui_get_state()
|
|
||||||
await quart.websocket.send(json.dumps(groups))
|
|
||||||
await self._queue_change_ev.wait()
|
|
||||||
|
|
||||||
def _ui_get_state(self):
|
|
||||||
response = []
|
|
||||||
for id, item in self.requests.items():
|
|
||||||
if item.judgement is not None:
|
|
||||||
response.append((id, item.describe()))
|
|
||||||
return response
|
|
|
@ -1,75 +0,0 @@
|
||||||
<!DOCTYPE html>
|
|
||||||
<html lang="en" dir="ltr">
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<title>Moderatuin qyeye</title>
|
|
||||||
<script type="importmap">
|
|
||||||
{
|
|
||||||
"imports": { "vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js" }
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script id="initial_state" type='text/kdl'>
|
|
||||||
<< init_state|safe >>
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script type="module">
|
|
||||||
import { createApp, ref, onMounted } from 'vue'
|
|
||||||
|
|
||||||
createApp({
|
|
||||||
setup() {
|
|
||||||
const scriptEl = document.getElementById("initial_state");
|
|
||||||
const groups = ref(JSON.parse(scriptEl.innerHTML));
|
|
||||||
onMounted(() => {
|
|
||||||
const websock = new WebSocket('<<url_for(".monitor")>>');
|
|
||||||
websock.addEventListener('message', (msg) => {
|
|
||||||
groups.value = JSON.parse(msg.data);
|
|
||||||
})
|
|
||||||
})
|
|
||||||
return { groups }
|
|
||||||
},
|
|
||||||
}).mount('#app')
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body id="root">
|
|
||||||
<div id="app">
|
|
||||||
<div v-for="(id, data) in groups" class="group">
|
|
||||||
<h3>{{ id }}</h3>
|
|
||||||
<p>{{ data }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<style type="text/css">
|
|
||||||
#app {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: row;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
font-family: sans-serif;
|
|
||||||
gap: 8px;
|
|
||||||
}
|
|
||||||
p {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
h3 {
|
|
||||||
margin-right: 1em;
|
|
||||||
}
|
|
||||||
.group {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 4px;
|
|
||||||
}
|
|
||||||
.scene {
|
|
||||||
padding: 12px 24px;
|
|
||||||
user-select: none;
|
|
||||||
background-color: lightgray;
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
.scene.pending {
|
|
||||||
background-color: lightgoldenrodyellow;
|
|
||||||
}
|
|
||||||
.scene.active {
|
|
||||||
background-color: lightgreen;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</body>
|
|
||||||
</html>
|
|
|
@ -74,12 +74,14 @@ class TextToSpeechPlugin(PluginBase):
|
||||||
if filename is None:
|
if filename is None:
|
||||||
filename = os.path.join(self.cache_dir, f'{uuid.uuid1()}.wav')
|
filename = os.path.join(self.cache_dir, f'{uuid.uuid1()}.wav')
|
||||||
|
|
||||||
|
self.logger.info(f'Generating TTS "{text}"...')
|
||||||
if self.speaker_wav:
|
if self.speaker_wav:
|
||||||
wav = self.synthesizer.tts(text, None, 'en', self.speaker_wav)
|
wav = self.synthesizer.tts(text, None, 'en', self.speaker_wav)
|
||||||
else:
|
else:
|
||||||
wav = self.synthesizer.tts(text)
|
wav = self.synthesizer.tts(text)
|
||||||
|
|
||||||
self.synthesizer.save_wav(wav, filename)
|
self.synthesizer.save_wav(wav, filename)
|
||||||
|
self.logger.info(f'Done - saved as {filename}')
|
||||||
return filename
|
return filename
|
||||||
|
|
||||||
async def run(self, text, *args, _ctx={}, wait=False, **kwargs):
|
async def run(self, text, *args, _ctx={}, wait=False, **kwargs):
|
||||||
|
|
Loading…
Add table
Reference in a new issue