ReadFeeder/README.md
2023-11-05 23:17:21 +01:00

6.2 KiB
Raw Blame History

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

  1. Git Repo clonen: git clone https://dev.spittank.org/daniel/ReadFeeder.git
  2. Bibliotheken installieren:
     pip install -r requirements.txt
    
  3. Konfigurationsbeispiel config.example.yml nach config.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

  1. Laden der Konfiguration und Initialisierung
  2. Laden des Feeds
  3. Für jeden Artikel
    1. Laden des Inhalts (entweder aus Titel oder Description, siehe Konfiguration)
    2. Anwenden der Filter (siehe Konfiguration)
    3. Hash generieren, falls Audiodatei zu diesem Hash noch nicht vorhanden…
      1. In Sätze aufteilen
      2. Zu jedem Satz einen Hash generieren, falls Audiodatei zu diesem Hash noch nicht vorhanden, diese mit TTS generieren
      3. Alle Sätze kombinieren
    4. 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.