Nach der ersten Installation von indi-allsky hatte ich verschiedene Kameras, Einstellungen und Testaufnahmen ausprobiert. Einige der damals erstellten Timelapses waren längst nicht mehr vorhanden. Im Videoviewer tauchten die alten Einträge aber weiterhin auf, teilweise als schwarze Kacheln ohne Vorschau.
Das wollte ich aufräumen. Allerdings nicht nach dem Motto „einfach alles vor einem bestimmten Datum löschen“, sondern so, dass produktive Aufnahmen unangetastet bleiben. In meinem Fall sollte der Videobestand erst ab dem 23. Dezember 2025 beginnen.
Und so bin ich vorgegangen …
Warum verschwinden gelöschte Videos nicht immer aus dem Videoviewer?
indi-allsky verwaltet Timelapses nicht nur als Dateien auf der SSD, sondern auch über Einträge in einer SQLite-Datenbank. Wird eine Datei außerhalb von indi-allsky entfernt, kann der dazugehörige Datenbankeintrag bestehen bleiben. Dann zeigt die Oberfläche unter Umständen noch ein Video an, obwohl das MP4 längst fehlt.
Bei mir betraf das Aufnahmen aus der frühen Testphase im Dezember 2025 und sogar einige Einträge mit Datumsangaben aus Januar 2025. Die alten Dateien lagen teilweise in einem inzwischen entfernten Archivverzeichnis. Wichtig: Eine schwarze Kachel beweist für sich genommen noch nicht, dass das Video fehlt. Es kann auch nur das Vorschaubild betroffen sein.
1. Vorhandene Videoeinträge zählen
Die Datenbank meiner Installation liegt unter /var/lib/indi-allsky/indi-allsky.sqlite. Zunächst habe ich ausschließlich lesend geprüft, wie viele Einträge vor meinem gewählten Stichtag vorhanden waren:
sudo sqlite3 -header -column /var/lib/indi-allsky/indi-allsky.sqlite <<'SQL'
SELECT 'video' AS typ, COUNT(*) AS anzahl
FROM video WHERE "dayDate" < '2025-12-23'
UNION ALL
SELECT 'startrailvideo', COUNT(*)
FROM startrailvideo WHERE "dayDate" < '2025-12-23';
SQLDas Ergebnis: 26 normale Timelapses und 11 Startrail-Videos, insgesamt also 37 veraltete Einträge. Das maßgebliche Feld ist dayDate, also das Aufnahmedatum, nicht der Zeitpunkt, an dem die Datei eventuell nachträglich erstellt wurde.
Wer einen anderen Starttermin möchte, ersetzt 2025-12-23 entsprechend. Der Stichtag selbst bleibt durch die Bedingung < erhalten.
2. Erst prüfen, ob die Videodateien wirklich fehlen
Bevor ich irgendetwas gelöscht habe, habe ich in einem Testlauf sämtliche Kandidaten einzeln gegen das Dateisystem geprüft. Der folgende Befehl verändert die Datenbank nicht:
sudo python3 - <<'PYCODE'
import sqlite3
from pathlib import Path
DB = '/var/lib/indi-allsky/indi-allsky.sqlite'
MEDIA = Path('/var/www/html/allsky/images')
CUTOFF = '2025-12-23'
conn = sqlite3.connect(f'file:{DB}?mode=ro', uri=True)
conn.row_factory = sqlite3.Row
present = missing = linked_thumbnails = 0
for table in ('video', 'startrailvideo'):
rows = conn.execute(
f'SELECT id, "dayDate", filename, thumbnail_uuid '
f'FROM {table} WHERE "dayDate" < ? ORDER BY "dayDate", id',
(CUTOFF,)
).fetchall()
print(f'\n{table}: {len(rows)} Eintraege')
for row in rows:
path = Path(row['filename'])
if not path.is_absolute():
path = MEDIA / path
exists = path.is_file()
present += bool(exists)
missing += not exists
thumb = 0
if row['thumbnail_uuid']:
thumb = conn.execute(
'SELECT COUNT(*) FROM thumbnail WHERE uuid = ?',
(row['thumbnail_uuid'],)
).fetchone()[0]
linked_thumbnails += thumb
print(row['dayDate'], row['id'],
'VORHANDEN' if exists else 'FEHLT',
f'Thumbnail-DB: {thumb}', row['filename'])
print('\nVideodateien vorhanden:', present)
print('Videodateien fehlen:', missing)
print('Verknuepfte Thumbnail-Eintraege:', linked_thumbnails)
print('KEINE AENDERUNGEN')
conn.close()
PYCODEIn meinem Fall war das Ergebnis eindeutig: 37 Datenbankeinträge, 37 fehlende Videodateien und keine zugehörigen Thumbnail-Datensätze. Damit war klar, dass ich keine noch vorhandenen MP4-Dateien aus dieser Auswahl verlieren würde. Hinweis: Der gezeigte Medienpfad entspricht meiner Installation; bei abweichender Konfiguration muss er angepasst werden.
3. Vor dem Bereinigen ein aktuelles Datenbankbackup erstellen
Vor einem Eingriff in die produktive SQLite-Datenbank ist eine aktuelle Sicherung Pflicht. indi-allsky bringt dafür eine eigene Backupfunktion mit:
cd ~/indi-allsky
./misc/indi-allsky-ctl backup-dbAnschließend sollte Backup completed erscheinen. Die neue Sicherung liegt normalerweise unter /var/lib/indi-allsky/backup/. Optional lässt sie sich mit gzip -t prüfen:
BACKUP="$(ls -t /var/lib/indi-allsky/backup/backup_indi-allsky_*.sqlite.gz | head -1)"
gzip -t "$BACKUP" && echo 'GZIP OK' Eine bestandene GZIP-Prüfung ersetzt keine SQLite-Integritätsprüfung. Wer besonders sorgfältig vorgehen möchte, entpackt die Sicherung in eine temporäre Datei und prüft sie mit PRAGMA integrity_check;. Bei mir war die SQLite-Prüfung bereits erfolgreich durchgeführt worden.
4. Die alten Einträge über indi-allsky bereinigen
Ich wollte nicht einfach DELETE FROM video ausführen. indi-allsky hat mit deleteAsset() eine eigene Routine, die bei Bedarf auch zugeordnete Thumbnails und Mediendateien behandelt. Außerdem muss der eigentliche Datenbankeintrag über die SQLAlchemy-Sitzung entfernt werden.
Wichtig: Der folgende Bereinigungslauf ist ausdrücklich auf meine beiden Videotabellen und den Stichtag beschränkt. Er bricht ab, sobald er bei einem Kandidaten doch noch eine vorhandene Videodatei oder einen zugeordneten Thumbnail-Datensatz entdeckt. Die endgültige Löschung startet nur mit dem Parameter --apply.
Zunächst das kleine Hilfsscript speichern:
cat > ~/cleanup_old_timelapses.py <<'PYCODE'
#!/usr/bin/env python3
import argparse
from datetime import date
from indi_allsky.flask import create_app, db
from indi_allsky.flask.models import (
IndiAllSkyDbVideoTable,
IndiAllSkyDbStarTrailsVideoTable,
IndiAllSkyDbThumbnailTable,
)
parser = argparse.ArgumentParser()
parser.add_argument('--apply', action='store_true',
help='Eintraege tatsaechlich entfernen')
args = parser.parse_args()
cutoff = date(2025, 12, 23)
app = create_app()
with app.app_context():
entries = []
for model in (IndiAllSkyDbVideoTable,
IndiAllSkyDbStarTrailsVideoTable):
entries.extend(model.query.filter(model.dayDate < cutoff).all())
print(f'Betroffene Eintraege: {len(entries)}')
if not entries:
print('Nichts zu tun.')
raise SystemExit(0)
for entry in entries:
print(entry.__class__.__name__, entry.id,
entry.dayDate, entry.filename)
if entry.getFilesystemPath().exists():
raise SystemExit('ABBRUCH: Video existiert noch: ' + entry.filename)
if entry.thumbnail_uuid:
thumb = IndiAllSkyDbThumbnailTable.query.filter_by(
uuid=entry.thumbnail_uuid).first()
if thumb is not None:
raise SystemExit('ABBRUCH: Thumbnail-Eintrag vorhanden')
if not args.apply:
print('TESTLAUF: Keine Aenderungen. Fuer Loeschung --apply angeben.')
raise SystemExit(0)
for entry in entries:
entry.deleteAsset()
db.session.delete(entry)
db.session.commit()
print(f'BEREINIGUNG ERFOLGREICH: {len(entries)} Eintraege entfernt')
PYCODEDanach zunächst nur den Testlauf ausführen:
cd ~/indi-allsky
./virtualenv/indi-allsky/bin/python ~/cleanup_old_timelapses.pyWenn die angezeigten IDs und Datumsangaben passen, die Sicherung geprüft ist und tatsächlich keine Dateien mehr existieren, kann man den gezielten Löschlauf freigeben:
cd ~/indi-allsky
./virtualenv/indi-allsky/bin/python ~/cleanup_old_timelapses.py --applyAchtung: Das ist ein tatsächlicher Datenbankeingriff. Die deleteAsset()-Funktion kann grundsätzlich auch Dateien löschen; deshalb steht vor der Ausführung die zusätzliche Existenzprüfung. Dieses Vorgehen sollte nicht ungeprüft auf andere Tabellen oder Installationsversionen übertragen werden. Ein Datenbankbackup allein stellt keine bereits gelöschten MP4-Dateien wieder her.
5. Ergebnis kontrollieren
Zum Abschluss habe ich erneut gezählt, ob noch Videoeinträge vor dem Stichtag existieren:
sudo sqlite3 -header -column /var/lib/indi-allsky/indi-allsky.sqlite <<'SQL'
SELECT 'video' AS typ, COUNT(*) AS verblieben
FROM video WHERE "dayDate" < '2025-12-23'
UNION ALL
SELECT 'startrailvideo', COUNT(*)
FROM startrailvideo WHERE "dayDate" < '2025-12-23';
SQLBei mir stand anschließend in beiden Zeilen 0. Nach dem Neuladen des indi-allsky-Videoviewers waren die alten schwarzen Kacheln tatsächlich verschwunden.
Was ist mit neueren Videos ohne Vorschaubild?
Hier wäre ich zurückhaltender. Ein fehlendes Thumbnail ist nicht dasselbe wie eine fehlende Videodatei. Neuere Timelapses, die auf der SSD existieren, sollten erhalten bleiben. Bei solchen Fällen ist es sinnvoller, die Thumbnail-Erzeugung zu prüfen, beispielsweise anhand des mitgelieferten Scripts misc/create_thumbnails.py, statt die Videos pauschal zu löschen.
Auch das indi-allsky-Werkzeug misc/validate_db_entries.py sollte man nicht einfach blind starten: Es prüft nicht nur Videos, sondern zahlreiche Medienkategorien und kann fehlende Einträge umfassend aus der Datenbank entfernen. Für meinen ganz konkreten Fall war die auf zwei Videotabellen und einen Stichtag begrenzte Bereinigung deshalb die passendere Lösung.
Fazit
Nach Installationen, Kamerawechseln und ersten Experimenten können sich in indi-allsky durchaus Altlasten ansammeln. Die zugehörigen Dateien sind vielleicht längst weg, ihre Einträge in der Datenbank aber noch vorhanden.
In meinem Fall waren es 37 alte Timelapse- und Startrail-Einträge, die vor dem 23. Dezember 2025 lagen. Nach einem lesenden Testlauf, einem frischen Backup und der gezielten Bereinigung waren sie aus dem Videoviewer verschwunden. Alle neueren Einträge blieben erhalten.
Die wichtigste Erkenntnis: Nicht jede fehlende Vorschau ist ein Grund, ein Video zu löschen. Erst prüfen, ob die Datei wirklich fehlt, dann gezielt aufräumen.
Wer sich außerdem für mein neues Sicherungskonzept interessiert: Meine früheren Anleitungen zum Datenbank- und Konfigurationsbackup (Phase 1) und zur Dateisicherung (Phase 2) dokumentieren noch die ursprüngliche Variante.