feat: translate subtitles with an OpenAI-compatible LLM
This commit is contained in:
1 parent
48cac86d60
commit
4665bf632a
21 files changed
+1877
-5
No files matched your search
@@ -0,0 +1,91 @@
|
||||
#pragma once
|
||||
|
||||
#include "llmclient.h"
|
||||
#include "subtitleextractor.h"
|
||||
|
||||
#include <QCoroTask>
|
||||
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QUrl>
|
||||
#include <QVariantMap>
|
||||
#include <QtQml/qqmlregistration.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
// Translates a whole subtitle track with an LLM, batch by batch, and caches the result
|
||||
// as an .srt file that mpv can load as the secondary subtitle.
|
||||
class TranslationService : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
QML_ELEMENT
|
||||
|
||||
Q_PROPERTY(bool busy READ isBusy NOTIFY busyChanged)
|
||||
Q_PROPERTY(double progress READ progress NOTIFY progressChanged)
|
||||
Q_PROPERTY(QString statusText READ statusText NOTIFY statusTextChanged)
|
||||
Q_PROPERTY(QString errorText READ errorText NOTIFY errorTextChanged)
|
||||
Q_PROPERTY(QStringList availableModels READ availableModels NOTIFY availableModelsChanged)
|
||||
Q_PROPERTY(bool fetchingModels READ isFetchingModels NOTIFY fetchingModelsChanged)
|
||||
|
||||
public:
|
||||
explicit TranslationService(QObject *parent = nullptr);
|
||||
~TranslationService() override;
|
||||
|
||||
bool isBusy() const;
|
||||
double progress() const;
|
||||
QString statusText() const;
|
||||
QString errorText() const;
|
||||
QStringList availableModels() const;
|
||||
bool isFetchingModels() const;
|
||||
|
||||
// \a track is an entry of MpvItem::subtitleTracks.
|
||||
Q_INVOKABLE void translate(const QUrl &videoUrl, const QVariantMap &track, const QString &mediaTitle);
|
||||
Q_INVOKABLE void cancel();
|
||||
// Asks the API configured in the settings for its models.
|
||||
Q_INVOKABLE void fetchModels();
|
||||
Q_INVOKABLE void clearError();
|
||||
|
||||
Q_SIGNALS:
|
||||
void busyChanged();
|
||||
void progressChanged();
|
||||
void statusTextChanged();
|
||||
void errorTextChanged();
|
||||
void availableModelsChanged();
|
||||
void fetchingModelsChanged();
|
||||
void translated(const QUrl &subtitleUrl, bool fromCache);
|
||||
|
||||
private:
|
||||
struct Job;
|
||||
struct Batches;
|
||||
|
||||
QCoro::Task<> run(QUrl videoUrl, QVariantMap track);
|
||||
QCoro::Task<> runFetchModels();
|
||||
// Translates \a lines, retrying failures and asking again for lines the model skipped.
|
||||
QCoro::Task<LlmClient::BatchResult> translateLines(std::shared_ptr<Job> job, QStringList lines, QStringList context);
|
||||
// Takes batches from \a batches until none are left; several run side by side.
|
||||
QCoro::Task<> translateBatches(std::shared_ptr<Job> job, std::shared_ptr<Batches> batches);
|
||||
QCoro::Task<Subtitles::ExtractResult> loadCues(std::shared_ptr<Job> job, QUrl videoUrl, QVariantMap track);
|
||||
|
||||
// Reads the settings and the API key. The second value is an error message when
|
||||
// something is missing.
|
||||
QCoro::Task<std::pair<LlmClient::Config, QString>> loadConfig();
|
||||
void fail(const std::shared_ptr<Job> &job, const QString &error);
|
||||
|
||||
void setBusy(bool busy);
|
||||
void setProgress(double progress);
|
||||
void setStatusText(const QString &text);
|
||||
void setErrorText(const QString &text);
|
||||
void setFetchingModels(bool fetching);
|
||||
|
||||
QNetworkAccessManager *m_network;
|
||||
std::shared_ptr<Job> m_job;
|
||||
bool m_busy = false;
|
||||
double m_progress = 0.0;
|
||||
QString m_statusText;
|
||||
QString m_errorText;
|
||||
QStringList m_availableModels;
|
||||
bool m_fetchingModels = false;
|
||||
};
|
||||
Reference in new issue
Block a user