Russian narration for the Enshrouded notes: mod 0.4.0, installer, generation pipeline
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
"""Step 3: the text for the voice, cut into segments (work/segs.json).
|
||||
|
||||
Every note: lexicon.pre -> lines (a blank line = paragraph 'p', a single newline = 'l') -> lines over
|
||||
MAXC characters cut at sentence ends into near-equal pieces ('s') -> RUAccent '+' -> lexicon.post ->
|
||||
U+0301 text for the ru-stress model.
|
||||
A segment's takes are named <id>_<hash>_s<seed>.wav, the hash of the reference and the spoken text:
|
||||
change the lexicon or the reference and only the segments it touches are rendered again.
|
||||
"""
|
||||
import hashlib
|
||||
import json
|
||||
import math
|
||||
import re
|
||||
|
||||
from .accent import acute_marks, plus_marks
|
||||
from .config import load
|
||||
from .lexicon import post, pre
|
||||
|
||||
MAXC = 380
|
||||
|
||||
|
||||
def split_long(s):
|
||||
if len(s) <= MAXC:
|
||||
return [s]
|
||||
sents = [x.strip() for x in re.findall(r".+?(?:[.!?…]+[»\"')]*(?=\s)|$)\s*", s) if x.strip()]
|
||||
k = math.ceil(len(s) / 330)
|
||||
target, out, cur = len(s) / k, [], ""
|
||||
for x in sents:
|
||||
if cur and len(cur) + len(x) + 1 > target * 1.15 and len(out) < k - 1:
|
||||
out.append(cur); cur = x
|
||||
else:
|
||||
cur = (cur + " " + x).strip()
|
||||
out.append(cur)
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
cfg = load()
|
||||
ref = cfg["voice"]["reference"]
|
||||
notes = json.load(open(cfg.w("notes.json"), encoding="utf-8"))
|
||||
if cfg.only: # ENSVOICE_NOTES=n016,n238: a quick experiment on a few notes
|
||||
notes = [n for n in notes if n["k"] in cfg.only]
|
||||
segs = []
|
||||
for n in notes:
|
||||
units, join = [], "p"
|
||||
for line in pre(n["text"]).split("\n"):
|
||||
line = line.strip()
|
||||
if not line:
|
||||
join = "p"; continue
|
||||
for j, piece in enumerate(split_long(line)):
|
||||
units.append(("s" if j else join, piece))
|
||||
join = "l"
|
||||
for i, (jn, u) in enumerate(units):
|
||||
plus = post(plus_marks(u))
|
||||
acute = acute_marks(plus)
|
||||
sid = f"{n['k']}_{i:02d}"
|
||||
h = hashlib.sha1(f"{ref}|{acute}".encode()).hexdigest()[:10]
|
||||
segs.append(dict(id=sid, take=f"{sid}_{h}", k=n["k"], i=i, join=jn if i else "-",
|
||||
text=u, plus=plus, acute=acute))
|
||||
json.dump(segs, open(cfg.w("segs.json"), "w", encoding="utf-8"), ensure_ascii=False, indent=0)
|
||||
L = [len(s["text"]) for s in segs]
|
||||
print("segments", len(segs), "notes", len(notes), "longest", max(L), "chars", sum(L))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user