Skip to content

Commit

Permalink
Allow choosing ffmpeg path in recording export
Browse files Browse the repository at this point in the history
Useful on Windows where nothing is in your PATH and manipulating it
requires at least a BSc in computer science. The error about being
unable to start ffmpeg will now also tell you how to get it: download
from ffmpeg.org on Windows, install through Homebrew on macOS and use
your package manager on Linux.

This should also now handle errors when starting the exporter properly,
instead of getting stuck in some limbo state where you can't restart the
export. Instead, it will properly dispose of the exporter and re-show
the export dialog if starting the process failed.
  • Loading branch information
askmeaboutlo0m committed Sep 23, 2023
1 parent e72a218 commit c50eb4e
Show file tree
Hide file tree
Showing 11 changed files with 162 additions and 86 deletions.
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Unreleased Version 2.2.0-pre
* Fix: Make Erase, Divide and Subtract layer modes in ORA files compatible with Krita.
* Feature: Stick ID alias and listing hosting options behind an advanced options checkbox, since they keep causing confusion.
* Fix: Make host page in the start dialog work properly on Arabic and other right-to-left languages.
* Feature: Allow choosing ffmpeg path on Windows. Thanks xxxx for suggesting.

2023-08-26 Version 2.2.0-beta.7
* Fix: Make classic brushes not go brighter when smudging into transparency. Thanks to cada for reporting.
Expand Down
62 changes: 37 additions & 25 deletions src/desktop/dialogs/playbackdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,50 +303,62 @@ void PlaybackDialog::keyPressEvent(QKeyEvent *event)
#ifndef Q_OS_ANDROID
void PlaybackDialog::onVideoExportClicked()
{
QScopedPointer<VideoExportDialog> dialog(new VideoExportDialog(this));
VideoExporter *ve = nullptr;

// Loop until the user has selected a valid exporter
// configuration or cancelled.
while(!ve) {
if(dialog->exec() != QDialog::Accepted)
return;

ve = dialog->getExporter();
}
VideoExportDialog *dlg = new VideoExportDialog(this);
dlg->setAttribute(Qt::WA_DeleteOnClose);
dlg->setWindowModality(Qt::WindowModal);
connect(dlg, &QDialog::accepted, this, [this, dlg]() {
startVideoExport(dlg->getExporter());
});
dlg->show();
}

m_exporter = ve;
void PlaybackDialog::startVideoExport(VideoExporter *exporter)
{
m_exporter = exporter;
m_exporter->setParent(this);
m_exporter->start();

m_ui->exportStack->setCurrentIndex(0);
m_ui->saveFrame->setEnabled(true);
connect(m_exporter, &VideoExporter::exporterFinished, this, [this]() {
setPlaying(false);
m_ui->exportStack->setCurrentIndex(1);
});
connect(
m_exporter, &VideoExporter::exporterFinished, m_exporter,
&VideoExporter::deleteLater);

connect(
m_exporter, &VideoExporter::exporterFinished, this,
&PlaybackDialog::videoExporterFinished);
connect(
m_exporter, &VideoExporter::exporterError, this,
[this](const QString &msg) {
setPlaying(false);
QMessageBox::warning(this, tr("Video error"), msg);
});

&PlaybackDialog::videoExporterError);
connect(
m_ui->saveFrame, &QAbstractButton::clicked, this,
&PlaybackDialog::exportFrame);
connect(
m_ui->stopExport, &QAbstractButton::clicked, m_exporter,
&VideoExporter::finish);

connect(
m_exporter, &VideoExporter::exporterReady, this,
&PlaybackDialog::onExporterReady);
}

void PlaybackDialog::videoExporterError(const QString &msg)
{
setPlaying(false);
QMessageBox::warning(this, tr("Video error"), msg);
}

void PlaybackDialog::videoExporterFinished(bool showExportDialogAgain)
{
setPlaying(false);
m_ui->exportStack->setCurrentIndex(1);

if(m_exporter) {
m_exporter->deleteLater();
m_exporter = nullptr;
}

if(showExportDialogAgain) {
QMetaObject::invokeMethod(
this, "onVideoExportClicked", Qt::QueuedConnection);
}
}
#endif

void PlaybackDialog::exportFrame(int count)
Expand Down
6 changes: 6 additions & 0 deletions src/desktop/dialogs/playbackdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ private slots:
void onBuildIndexClicked();
#ifndef Q_OS_ANDROID
void onVideoExportClicked();
void videoExporterError(const QString &msg);
void videoExporterFinished(bool showExportDialogAgain);
#endif

void exportFrame(int count = 1);
Expand All @@ -65,6 +67,10 @@ private slots:
void updateButtons();
static bool isErrorResult(DP_PlayerResult result);

#ifndef Q_OS_ANDROID
void startVideoExport(VideoExporter *exporter);
#endif

Ui_PlaybackDialog *m_ui;
canvas::PaintEngine *m_paintengine;
QPointer<VideoExporter> m_exporter;
Expand Down
36 changes: 31 additions & 5 deletions src/desktop/dialogs/videoexportdialog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,12 @@ VideoExportDialog::VideoExportDialog(QWidget *parent) :
settings.bindVideoExportFrameWidth(m_ui->framewidth);
settings.bindVideoExportFrameHeight(m_ui->frameheight);
settings.bindVideoExportSizeChoice(m_ui->sizeChoice, std::nullopt);
settings.bindVideoExportFfmpegPath(m_ui->ffmpegPathEdit);
settings.bindVideoExportFfmpegPath(this, &VideoExportDialog::updateUi);
settings.bindVideoExportCustomFfmpeg(m_ui->ffmpegCustom);

// Check for ffmpeg
m_ui->ffmpegNotFoundWarning->setHidden(FfmpegExporter::checkIsFfmpegAvailable());
connect(
m_ui->ffmpegPathButton, &QAbstractButton::clicked, this,
&VideoExportDialog::chooseFfmpegPath);

updateUi();
}
Expand All @@ -80,6 +82,22 @@ VideoExportDialog::~VideoExportDialog()
delete m_ui;
}

void VideoExportDialog::chooseFfmpegPath()
{
#ifdef Q_OS_WINDOWS
QString executableFilter =
//: Used for picking a kind of file, used like "Executables (*.exe)".
QStringLiteral("%1 (*.exe)").arg(tr("Executables"));
#else
QString executableFilter;
#endif
QString ffmpegPath = QFileDialog::getOpenFileName(
this, tr("Choose ffmpeg path"), QString(), executableFilter);
if(!ffmpegPath.isEmpty()) {
m_ui->ffmpegPathEdit->setText(ffmpegPath);
}
}

void VideoExportDialog::updateUi()
{
VideoExporter::Format format =
Expand All @@ -98,7 +116,8 @@ void VideoExportDialog::updateUi()
}
args.append({"-y", "<FILENAME>"});

m_ui->ffmpegBasics->setText("ffmpeg " + args.join(QChar(' ')));
m_ui->ffmpegBasics->setText(QStringLiteral("%1 %2").arg(
getFfmpegPath(), args.join(QChar(' '))));
m_ui->ffmpegCustomLabel->setVisible(format == VideoExporter::FFMPEG_CUSTOM);
m_ui->ffmpegCustom->setVisible(format == VideoExporter::FFMPEG_CUSTOM);
}
Expand Down Expand Up @@ -136,6 +155,12 @@ VideoExporter *VideoExportDialog::getExporter()
return ve;
}

QString VideoExportDialog::getFfmpegPath()
{
QString path = m_ui->ffmpegPathEdit->text().trimmed();
return path.isEmpty() ? QStringLiteral("ffmpeg") : path;
}

VideoExporter *VideoExportDialog::getImageSeriesExporter()
{
QString dir = FileWrangler{this}.getSaveAnimationFramesPath();
Expand Down Expand Up @@ -166,7 +191,8 @@ VideoExporter *VideoExportDialog::getFfmpegExporter(VideoExporter::Format format
return nullptr;
} else {
return new FfmpegExporter{
format, filename, m_ui->ffmpegCustom->toPlainText()};
format, getFfmpegPath(), filename,
m_ui->ffmpegCustom->toPlainText()};
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/desktop/dialogs/videoexportdialog.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@ class VideoExportDialog final : public QDialog
VideoExporter *getExporter();

private slots:
void chooseFfmpegPath();
void updateUi();

private:
QString getFfmpegPath();
VideoExporter *getImageSeriesExporter();
VideoExporter *getFfmpegExporter(VideoExporter::Format format);

Expand Down
1 change: 1 addition & 0 deletions src/desktop/settings_table.h
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@ SETTING(twoFingerRotate , TwoFingerRotate , "settings/input/
SETTING(twoFingerZoom , TwoFingerZoom , "settings/input/touchpinch" , true)
SETTING(updateCheckEnabled , UpdateCheckEnabled , "settings/updatecheck" , true)
SETTING(videoExportCustomFfmpeg , VideoExportCustomFfmpeg , "videoexport/customffmpeg" , QString())
SETTING(videoExportFfmpegPath , VideoExportFfmpegPath , "videoexport/ffmpegpath" , QString("ffmpeg"))
SETTING(videoExportFormat , VideoExportFormat , "videoexport/formatchoice" , VideoExporter::Format::IMAGE_SERIES)
SETTING(videoExportFrameHeight , VideoExportFrameHeight , "videoexport/frameheight" , 720)
SETTING(videoExportFrameRate , VideoExportFrameRate , "videoexport/fps" , 30)
Expand Down
Loading

0 comments on commit c50eb4e

Please sign in to comment.