Grammar check as a measurement of quality

Endreader (text consumer) rarely enjoys reading incorrect text.
But the real life authors do make mistakes
(humans, nothing stops ai from writing a orthographically perfect book)
That need explains the existence of proofreading concept.
To try and deal with some (of many) mistakes in previous results,
it would be helpful to find some of the worst mistakes/pages recognized

Although for me volume 12 was readable (by my standard).
The same cannot be said for volume 13.
So, from this page forward, I am writing about volume 13
(pretty much all the steps with v12 were applied to v13)

Script to detect quality of the output (quality_check.py)

#!/usr/bin/env python

import sys
import enchant

textfile = sys.argv[1]

# use example: ./quality_check.py text/ffmpeg_2.txt

non_words = "\n,.;!?'"
ge_dict = enchant.Dict('de_DE')

def word_ratio(words):
    sane = [ge_dict.check(w) for w in words if w not in non_words]
    if len(sane) == 0:
        return 0, 0
    return sum(sane) / len(sane), len(sane)

def read_into_list(filename):
    with open(filename, "r") as lf:
        return lf.read().split()

if __name__ == "__main__":
    words = read_into_list(textfile)
    ratio, length = word_ratio(words)
    print(f"{ratio}:{length}:{textfile}")

read_into_list returns list of words in the file

>>> words = open("ffmpeg_002.txt").read().split()
>>> words
['DOie', 'Belagerung', 'Teil', '1', 'Das', 'Ende', 'des', 'Winters', 'war', 'noch', 'weit', 'entfernt', 'und', 'die', 'Luft', 'war', 'kalt,', 'obwohl', 'er', '@s', 'nicht', 'spürte,', 'Das', 'war', 'seinem', 'Fell', 'zu', 'verdanken.,', 'Sein', 'ganzer', 'Körper', 'war', 'mit', 'glänzendem', 'schwarzem', 'Fell', 'bedeckt,', 'und', 'ein', 'Kleidungsstück', 'darüber', 'würde', 'für', 'eine', 'hervorragende', 'Isolierung', 'sorgen.', 'Er', 'würde', 'nicht', 'zittern,', 'selbst', 'wenn', 'er', '$tattdessen', 'einen', 'Anzug',
'aus', 'metallischer', 'Vollplattenrüstung', 'trug.', 'Allerdings', 'zitterte', 'er', 'jetzt', 'aus', 'einem', 'anderen', 'Grund.', 'Dieser', 'Grund', 'war', 'Wut.', 'Diesen', 'enorsen', 'Zorn', 'Zorn', 'zu', 'mennen,', 'wäre', 'nicht', 'allzu', 'weit', 'entfernt.', '£in', 'leises', 'Knurren', 'entkam', 'ihm', '-', 'wie', 'das,', 'was', 'ein', 'fleischfressendes', 'Tier', 'machen', 'würde', '-', 'und', 'er', 'schnalzte', 'verlegen', 'mit', 'der', 'Zunge.', 'Für', 'Witglieder', 'seiner', 'Rasse', '-', 'die', 'Zoas', 'ti', '-', 'war', 'es', 'ein', 'Beweis', 'dafür,', 'dass', 'sie', 'Äihre', 'Gefühle', 'nicht', 'kontrollieren', 'konnten,', 'wenn', 'sie', 'Tiergeräusche', 'machten.', 'eine', 'beschämende', 'Darstellung', 'für', 'einen', 'Erwachsenen.', 'Dies', 'war', 'jedoch', 'nur', 'unter', 'Kollegen', 'seiner', 'Spezies,', 'Jeder', 'andere,', 'der', 'dieses', 'Knurren', 'zwischen', 'seinen', 'scharfen', 'Zähnen', 'hörte,', 'hätte', '‚vor', 'Angst', 'gezittert', 'oder', 'vor', 'Angst', 'gefroren,', 'Er', 'drehte', 'der', 'menschlichen', 'Stadt', 'den', 'Rücken', 'zu,', 'auf', 'die', 'er', 'gerade', 'gestarrt', 'hatte,', 'und', 'kehrte', 'in', 'sein', 'Lager', 'zurück,', 'Ihr', 'Oberbefehlshaber', 'war', 'Yaldabaoth,', 'ihr', 'Merrscher,', 'der', 'Oberwältigende', 'Macht', 'ausübte.', 'Unter', 'ihm', 'versammelten', 'sich', 'viele', 'Rassen,', 'und', 'jeden', 'Tag', 'kam', '@s', 'zu', 'vielen', 'sinnlosen', 'Streitigkeiten', 'zwischen', 'ihnen.']

non_words = "\n,.;!?-'"

avoids symbols that not acceptable by the enchant

>>> ge_dict = enchant.Dict("de_DE")
>>> ge_dict.check("!")
False
>>> ge_dict.check("hallo!")
False

script returns a string with ':' as separator between ratio, number of words and path of the file

./quality_check.py overlord_audiobooks/vol_13/13_1.txt 2>/dev/null
0.813456818978614:68456:overlord_audiobooks/vol_13/13_1.txt

where 0.813456818978614 is the score of the first book of the 13 volume
by getting score for each page one can sort them by the score value and find the most problem part(s)

for f in overlord_audiobooks/vol_13/text/*.txt; \
do ./quality_check.py "$f" >> overlord_audiobooks/vol_13/quality_check.txt; \
done

now we have the file with the score for each page, number of words in the page and its filepath

# looking at quality_check.txt
head quality_check.txt
0.8333333333333334:210:overlord_audiobooks/vol_13/text/ffmpeg_002.txt
0.8475336322869955:223:overlord_audiobooks/vol_13/text/ffmpeg_003.txt
0.841897233201581:253:overlord_audiobooks/vol_13/text/ffmpeg_004.txt
0.7876106194690266:226:overlord_audiobooks/vol_13/text/ffmpeg_005.txt
0.8267148014440433:277:overlord_audiobooks/vol_13/text/ffmpeg_006.txt
0.7956989247311828:279:overlord_audiobooks/vol_13/text/ffmpeg_007.txt
0.8229166666666666:288:overlord_audiobooks/vol_13/text/ffmpeg_008.txt
0.8171206225680934:257:overlord_audiobooks/vol_13/text/ffmpeg_009.txt
0.82:300:overlord_audiobooks/vol_13/text/ffmpeg_010.txt
0.8122605363984674:261:overlord_audiobooks/vol_13/text/ffmpeg_011.txt

# five worst pages
sort quality_check.txt | head -n 5
0.6432432432432432:185:overlord_audiobooks/vol_13/text/ffmpeg_304.txt
0.6869565217391305:230:overlord_audiobooks/vol_13/text/ffmpeg_238.txt
0.6920152091254753:263:overlord_audiobooks/vol_13/text/ffmpeg_150.txt
0.6995708154506438:233:overlord_audiobooks/vol_13/text/ffmpeg_128.txt
0.7104247104247104:259:overlord_audiobooks/vol_13/text/ffmpeg_040.txt

# get filepath of the worst page
sort quality_check.txt | head -n 1 | awk -F ':' '{print $3}'
overlord_audiobooks/vol_13/text/ffmpeg_304.txt

looking inside of the worst page

Remedios "Gesichtsausdruck änderte sich und ergriff ihn,

Knappel Verdammt, es gibt Dinge, die du sagen kannst und die du nicht sagen
kannst!

Sie packte Najaas Kragen mit enormer Kraft und Näjaa fiel es schmer zu atmen.
Ihr beide! Beruhigen! Beruhige dich jetzt!

Die Paladine, Priester, Soldaten und dergleichen machten sich eilig auf den Weg
zwischen N3jaa und Remedios und zogen sie auseinander.

N3jaa kouchte mit aller Kraft, als sie rief:
Wir mussen eın feam aussenden, um Seıne Wajestät zu retten)

Dafür Können wir Unsere Ressourcen Micht verschwenden!

ie kannst du es wagen, e eine Verschwendung zu nennen!

Näjaa wollte hochgehen und Remedios schlagen, aber die Leute zwischen ıhnen
hielten sie auf.

Ich habe dir nichts zu sagen! Nachdem Najaa Sich etwas abgekühlt hatte, wandte
sie sich an die Leute, die xie festhielten.

Könntest du mich loslassen? Ich muss etwas tum:
kohin gehst du !7

Als Antwort auf diese Frage sah Najaa Remedios mit einem außerst Ungläubigen
Gesichtsausdruck an.

kas für Augen sind das? Sallte ein Knappe so einen Paladin ansehen?
Hm, schnaubte Naiaa.
Zubröt werda Ach Soise Mebeit, den Prinzen; Bitten; diäe AaLzNEENTIN FÜr en

low score caused by the low quality of the image frame itself;

frame made by ffmpeg

I tried some upscaling methods: results were poor

So there would be no page about upscaling, until|unless I find something that actually works good with text.