6.2 KiB
ReadFeeder
Dieses Skript lädt einen RSS-Feed und erstellt für neue und geänderte Einträge eine Audio-Datei via TTS. Anschließend wird diese Datei auf einem Mastodon-Account gepostet (oder jedem anderen Fediverse-Dienst mit Mastdon.py kompatibler API).
Installation
- Git Repo clonen:
git clone https://dev.spittank.org/daniel/ReadFeeder.git
- Bibliotheken installieren:
pip install -r requirements.txt
- Konfigurationsbeispiel
config.example.yml
nachconfig.yml
kopieren und Einstellungen anpassen.
Konfiguration
Die Konfiguration muss immer vollständig sein, es finden keinerlei Überprüfungen statt. Fehlende Konfigurationsparameter führen zu Programmfehlern.
Elevenlabs
elevenlabs:
enabled: false
api_key: <CHANGE_ME>
voice:
id: ODq5zmih8GrVes37Dizd
stability: 0.5
similarity_boost: 0.75
style: 0.0
use_speaker_boost: true
Soll für die Generierung ElevenLabs verwendet werden, muss dies mit enabled: true
aktiviert werden. Ansonsten wird gTTS verwendet. In diesem Fall muss auch ein api_key
hinterlegt werden und es kann eine Sprache und ihre Einstellungen festgelegt werden. Standardmäßig ist "Patrick" eingestellt.
Audio
audio:
artist: ReadFeeder
In diesem Abschnitt können Teile der Metadaten für die generierten Audiodateien angegeben werden, aktuell der artist
.
Mastodon
mastodon:
enabled: true
instance_url: <CHANGE_ME>
access_token: <CHANGE_ME>
visibility: private
post:
title: true
text: false
date: false
link: true
In diesem Abschnitt werden alle Mastodon betreffenden Einstellungen vorgenommen. Das Posten erfordert eine instance_url
und ein access_token
und kann mit enabled: false
auch komplett abgeschaltet werden.
Die visibility
legt fest, wer die Postings lesen kann:
- Nur Follower:
visibility: private
- Ungelistet:
visibility: unlisted
- Jeder:
visibility: public
Unter post
kann für jeden Bestandteil festgelegt werden, ob er im Post erscheinen soll. ACHTUNG: Es wird aktuell keine Größenkontrolle durchgeführt. Daher ist es sicherer, nicht den Text oder gar nichts (dann wird nur die generierte Datei gepostet) einzustellen.
RSS
rss:
feed_url: <CHANGE_ME>
use_field: title
In diesem Abschnitt müssen die Feedadresse (feed_url
) und das zu verwendende Feld (use_field
) angegeben werden. Das Feld kann z.B. title
oder description
sein. Der Volltext eines Artikels steht meist in description
, aber manche Feeds haben auch nur einen Titel.
Sprachen
languages:
default: en
used:
- en
- de
Die default
-Sprache wird für alle Sätze verwendet, die nicht zugeordnet werden könne oder deren Sprache nicht unterstützt wird.
Mit den Sprachen unter used
legt man eine Auswahl der Sprachen fest, die im Feed vorkommen können. Hiermit wird die Genauigkeit der Erkennung verbessert.
Filter
Da nicht alle Begriffe sauber generiert werden können (oder sollen), werden auf die Inhalte zwei Arten von Filtern angewendet.
Wortfilter
word_filter:
"...": "…"
Wortfilter erlauben einfache Ersetzungen nach dem Muster "original": "replacement"
.
RegEx-Filter
regex_filter:
"[tT]est": "Test"
RegEx-Filter erlauben komplexe Ersetzungen mit regulären Ausdrücken nach dem Muster "pattern": "replacement"
.
Verwendung
Das Skript kann direkt aufgerufen werden.
python main.py
Funktionsweise
Grundsätzlicher Ablauf
- Laden der Konfiguration und Initialisierung
- Laden des Feeds
- Für jeden Artikel
- Laden des Inhalts (entweder aus Titel oder Description, siehe Konfiguration)
- Anwenden der Filter (siehe Konfiguration)
- Hash generieren, falls Audiodatei zu diesem Hash noch nicht vorhanden…
- In Sätze aufteilen
- Zu jedem Satz einen Hash generieren, falls Audiodatei zu diesem Hash noch nicht vorhanden, diese mit TTS generieren
- Alle Sätze kombinieren
- Eintrag posten
Hashing und Generierung
Das Skript führt einige Schritte durch, um die Generierungsaufrufe gering zu halten. Dies bedeutet einerseits eine Reduktion der benötigten Zeit, andererseits eine Reduktion der Kosten für Aufrufe kostenpflichtiger APIs (etwa ElevenLabs).
Hierzu wird zunächst der Inhalt des Artikels gehasht. Der Artikel wird nur dann verarbeitet, wenn nicht bereits ein Audiodatei mit diesem Hash existiert. Dies sorgt außerdem dafür, dass geänderte Artikel auch sicher erneut generiert und gepostet werden.
Es handelt sich um simple MD5-Hashes, die über die normalisierten Texte (klein geschrieben, ohne Whitespaces) gebildet werden.
Bei der Generierung eines Artikels werden wiederum Hashes der einzelnen Sätze gebildet und diese, falls nicht vorhanden, generiert. Somit ist sichergestellt, dass bestehende Teile bestmöglich wiederverwendet werden und nicht bei kleinsten Änderungen der gesamte Artikel neu generiert werden muss.
Andererseits kann dies zu einer geringeren Audioqualität führen, da die einheitliche Tonalität des Artikels nicht sichergestellt werden kann. Es ist also ein Kompromiss zwischen Kürze der Sätze – und damit ihrer Wiederverwendbarkeit – sowie der Klangqualität zu finden.
Hierzu werden die Separatoren in der Funktion split_into_sentences
verwendet. Standardmäßig werden hier nur ?
, !
, .
und …
verwendet. Die Separatoren werden am Ende der Sätze belassen, sodass "Hallo!" und "Hallo?" damit unterschiedliche Sätze sind. Dies ist notwendig,
da die Satzzeichen die Betonung verändern können. Maximal aufteilen ließe sich der Text mit dem Separator
(Leerzeichen). Es würden dann sehr wenige Neugenerierungen erforderlich sein, jedoch wäre die Sprache sehr abgehackt.
Für die einzelnen Sätze wird jeweils die Sprache bestimmt. Dies ist in erster Linie für gTTS relevant, um die Qualität der Sprachausgabe zu verbessern. ElvenLabs hat ein mehrsprachiges Modell.
Die Generierung mit gTTS ist kostenlos (sie verwendet die Sprachausgabe von Google Translate). Die von ElevenLabs benötigt einen API-Key, ein (kleines) Gratispaket ist verfügbar.