Skip to content

Commit

Permalink
Trim only feature, multiple improvements
Browse files Browse the repository at this point in the history
Added the trim only feature,
Supports windows dpi scaling,
only scales the video or changes the framerate when needed
  • Loading branch information
andreasGBL committed Jul 16, 2022
1 parent 1a78422 commit 1cd7f60
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 42 deletions.
8 changes: 4 additions & 4 deletions include/ffmpegwrapper.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class FFMPEGWrapper
{
public:
FFMPEGWrapper();
bool exportFile(Video const & video, TrimSettings const & settings, double MBitRate, Resolution const & res, Codec const & codec, int HardwareAccelleration, int Framerate);
bool exportFile(Video const & video, TrimSettings const & settings, double MBitRate, Resolution const & res, Codec const & codec, int HardwareAccelleration, int Framerate, bool trimOnly);
private:
QString getFileName(QString const & filePath);
QString getExportFileName(QString const & fileName);
Expand All @@ -17,10 +17,10 @@ class FFMPEGWrapper

QString getTrimString(QTime const & start, QTime const & end, Video const & video);
QString getMBitRateString(double MBitRate);
QString getFramerateFilter(int Framerate);
QString getScaleFilterString(Resolution const & res, int HardwareAcceleration);
QString getFramerateFilter(double Framerate, double vidFramerate);
QString getScaleFilterString(Resolution const & res, Resolution const & vidRes, int HardwareAcceleration);

QString getVideoCodecString(Codec const & codec, int HardwareAcceleration);
QString getVideoCodecString(Codec const & codec, int HardwareAcceleration, bool trimOnly);
QString getAudioCodecString(bool canCopy);
QString getHardwareAccelerationString(int HardwareAcceleration, bool usesScaleFilter);
QString getInputFileString(QString const & filePath);
Expand Down
16 changes: 10 additions & 6 deletions include/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ struct Codec {
struct Video {
QString filePath;
QTime length;
Resolution resolution;
double framerate;
};

struct TrimSettings {
Expand All @@ -28,11 +30,13 @@ struct TrimSettings {
};

enum RESOLUTION_IDX {
RESOLUTION_AS_INPUT = 0,
K4 = 1,
p1080 = 2,
p720 = 3,
p480 = 4
RESOLUTION_AS_INPUT,
K4,
p1440,
p1080,
p720,
p480,
p240
};

enum HARDWARE_ACCELERATION {
Expand Down Expand Up @@ -72,7 +76,7 @@ Resolution const RESOLUTIONS[7] = {
}
};

int const FRAMERATES[5] = {
float const FRAMERATES[5] = {
0,
30,
60,
Expand Down
1 change: 1 addition & 0 deletions include/videolowwindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ private slots:
void quickHEVC_16();
void exportVideo();
void reviewVideo();
void quickTrimOnly();
void gotCutInformation(QTime start, QTime end, bool cancelled);
void startTimeEdited();
void endTimeEdited();
Expand Down
41 changes: 23 additions & 18 deletions src/ffmpegwrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ FFMPEGWrapper::FFMPEGWrapper()
}
}

bool FFMPEGWrapper::exportFile(const Video & video, const TrimSettings & settings, double MBitRate, const Resolution & res, const Codec & codec, int HardwareAccelleration, int Framerate)
bool FFMPEGWrapper::exportFile(const Video & video, const TrimSettings & settings, double MBitRate, const Resolution & res, const Codec & codec, int HardwareAccelleration, int Framerate, bool trimOnly)
{
const QString & filePath = video.filePath;
QString expFilePath = getExportFilePath(filePath);
Expand All @@ -33,12 +33,12 @@ bool FFMPEGWrapper::exportFile(const Video & video, const TrimSettings & setting

//filters
std::vector<QString> filters;
QString framerateFilter = getFramerateFilter(Framerate);
QString scaleFilter = getScaleFilterString(res, HardwareAccelleration);
QString framerateFilter = getFramerateFilter(Framerate, video.framerate);
QString scaleFilter = getScaleFilterString(res, video.resolution, HardwareAccelleration);

//options part2
QString audioCodec = getAudioCodecString(settings.start == QTime(0, 0) || !settings.trim);
QString videoCodec = getVideoCodecString(codec, HardwareAccelleration);
QString audioCodec = getAudioCodecString(settings.start == QTime(0, 0) || !settings.trim || trimOnly);
QString videoCodec = getVideoCodecString(codec, HardwareAccelleration, trimOnly);
QString bitrate = getMBitRateString(MBitRate);
QString outputFile = getOutputFileString(expFilePath);

Expand Down Expand Up @@ -118,17 +118,17 @@ QString FFMPEGWrapper::getMBitRateString(double MBitRate)
return "-b:v " + QString::number(MBitRate) + "M";
}

QString FFMPEGWrapper::getFramerateFilter(int Framerate)
QString FFMPEGWrapper::getFramerateFilter(double Framerate, double vidFramerate)
{
if (Framerate <= 0)
if (Framerate <= 0. || Framerate == vidFramerate)
return QString("");
else
return QString("fps=fps=") + QString::number(Framerate);
}

QString FFMPEGWrapper::getScaleFilterString(Resolution const & res, int HardwareAcceleration)
QString FFMPEGWrapper::getScaleFilterString(Resolution const & res, Resolution const& vidRes, int HardwareAcceleration)
{
if (res.height <= 0 && res.width <= 0) {
if (res.height <= 0 && res.width <= 0 || (res.height == vidRes.height && res.width == vidRes.width)) {
return QString("");
}
QString resolutionString = QString::number(res.width) + ":" + QString::number(res.height);
Expand All @@ -141,17 +141,22 @@ QString FFMPEGWrapper::getScaleFilterString(Resolution const & res, int Hardware
}
}

QString FFMPEGWrapper::getVideoCodecString(Codec const & codec, int HardwareAcceleration)
QString FFMPEGWrapper::getVideoCodecString(Codec const & codec, int HardwareAcceleration, bool trimOnly)
{
QString prefix = "-c:v ";
switch (HardwareAcceleration)
{
case(HARDWARE_ACCELERATION::NVIDIA):
return prefix + codec.NVIDIA.c_str();
case(HARDWARE_ACCELERATION::AMD):
return prefix + codec.AMD.c_str();
default:
return prefix + codec.defaultName.c_str();
if (trimOnly) {
return prefix + "copy";
}
else {
switch (HardwareAcceleration)
{
case(HARDWARE_ACCELERATION::NVIDIA):
return prefix + codec.NVIDIA.c_str();
case(HARDWARE_ACCELERATION::AMD):
return prefix + codec.AMD.c_str();
default:
return prefix + codec.defaultName.c_str();
}
}
}

Expand Down
52 changes: 46 additions & 6 deletions src/filedropwidget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,11 @@ void FileDropWidget::dropEvent(QDropEvent * event)
std::string cmd = "ffprobe.exe \"" + path.toStdString() + "\" 2>&1"; //redirect stderr to stdout
QString probe("");
int hours = 0, minutes = 0, seconds = 0, milliseconds = 0;
Resolution resolution = {0, 0};
double framerate = 0;
{
{
FILE * f;
FILE* f;
f = _popen(cmd.c_str(), "r");
char buff[128];
if (f) {
Expand All @@ -83,7 +85,7 @@ void FileDropWidget::dropEvent(QDropEvent * event)
}
}
}
// std::cout<<"Probe:"<<probe.toStdString()<<std::endl;
//std::cout << "Probe:" << probe.toStdString() << std::endl;
QString pattern("Duration: \\d{2}:\\d{2}:\\d{2}.\\d{2}");
QRegularExpression regex(pattern);

Expand All @@ -99,16 +101,54 @@ void FileDropWidget::dropEvent(QDropEvent * event)
seconds = static_cast<int>(timesplit[2].toDouble());
milliseconds = static_cast<int>((timesplit[2].toDouble() - static_cast<double>(seconds)) * 100.0) * 10;
}
}
QTime vidLength(hours, minutes, seconds, milliseconds); //TODO: do probing and thumbnail at 3 seconds in parallel (async) and redo thumbnail in rare case of a video that is shorter than 3 seconds

QString pattern2("(\\d{1,3}.\\d{2}|\\d{1,3}) fps");
regex = QRegularExpression(pattern2);
bool ok = true;

match = regex.match(probe);
if (match.hasMatch()) {
QString res = match.captured(0);
QString splitter(" fps");
QString fps = res.split(splitter)[0];
double frate = fps.trimmed().toDouble(&ok);
if (ok)
framerate = frate;
std::cout << "fps: "<<framerate << std::endl;

}

QString pattern3(", \\d{2,5}x\\d{2,5}(,| \\[)");
regex = QRegularExpression(pattern3);
match = regex.match(probe);
if (match.hasMatch()) {
QString res = match.captured(0);
QString splitter(",");
QString splitter2(" [");
QString splitter3("x");
QString res12 = res.split(splitter)[1].trimmed();
QString res2 = res12.split(splitter2)[0];
QString width = res2.split(splitter3)[0];
QString height = res2.split(splitter3)[1];
int w = width.toInt(&ok);
if (ok)
resolution.width = w;
int h = height.toInt(&ok);
if (ok)
resolution.height = h;
std::cout << "width: "<<resolution.width << " height: " << resolution.height << std::endl;
}

}
QTime vidLength(hours, minutes, seconds, milliseconds);
int msecsMid = vidLength.msecsSinceStartOfDay() / 2;
QTime thumbnailTime = QTime::fromMSecsSinceStartOfDay(msecsMid > 3000 ? 3000 : msecsMid); //prefer a thumbnail at 3 seconds or at videoLength / 2, if video is shorter
QString tempFolder("VideoLow.tmp");
QDir::temp().mkdir(tempFolder); //create temporary folder for thumbnail
QString thumbnail = QDir::tempPath()+QString("/"+tempFolder+"/thumb.jpg");
QString format("hh:mm:ss.zzz");

cmd = "ffmpeg -y -i \"" + path.toStdString() + "\" -ss " + thumbnailTime.toString(format).toStdString() + " -vf \"scale=600:600:force_original_aspect_ratio=decrease\" -vframes 1 \"" + thumbnail.toStdString() + "\" 2>&1"; //redirect stderr to stdout
cmd = "ffmpeg -y -i \"" + path.toStdString() + "\" -ss " + thumbnailTime.toString(format).toStdString() + " -vf \"scale=1000:1000:force_original_aspect_ratio=decrease\" -vframes 1 \"" + thumbnail.toStdString() + "\" 2>&1"; //redirect stderr to stdout
QString thumb;
{
FILE * f;
Expand All @@ -124,7 +164,7 @@ void FileDropWidget::dropEvent(QDropEvent * event)
QPixmap m(thumbnail);
auto scaled = m.scaled(previewLabel->width(), previewLabel->height(), Qt::KeepAspectRatio);
previewLabel->setPixmap(scaled);
Video vid = { path, vidLength};
Video vid = { path, vidLength, resolution, framerate};
emit newVideoFileDropped(vid);
hasDrop = true;
}
Expand Down
1 change: 1 addition & 0 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

int main(int argc, char *argv[])
{
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication a(argc, argv);
VideoLowWindow w;
w.show();
Expand Down
33 changes: 29 additions & 4 deletions src/videolowwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
#include <QMainWindow>
#include <QString>


#include "include/structs.h"

#include <iostream>
Expand All @@ -13,7 +12,9 @@ VideoLowWindow::VideoLowWindow(QWidget * parent)
, ffmpeg()
, ui(new Ui::VideoLowWindow)
{

ui->setupUi(this);
ui->centralwidget->resize(width() - 10, height() - 10);
ui->HardwareAccelerationComboBox->setCurrentIndex(HARDWARE_ACCELERATION_DEFAULT);
ui->HardwareAccelerationQuickComboBox->setCurrentIndex(HARDWARE_ACCELERATION_DEFAULT);
ui->HardwareAccelerationComboBox->update();
Expand All @@ -36,6 +37,7 @@ VideoLowWindow::~VideoLowWindow()

void VideoLowWindow::connectSlots()
{
QObject::connect(ui->trimVideoButton, &QPushButton::clicked, this, &VideoLowWindow::quickTrimOnly);
QObject::connect(ui->H264_2, &QPushButton::clicked, this, &VideoLowWindow::quickH264_2);
QObject::connect(ui->H264_4, &QPushButton::clicked, this, &VideoLowWindow::quickH264_4);
QObject::connect(ui->H264_8, &QPushButton::clicked, this, &VideoLowWindow::quickH264_8);
Expand Down Expand Up @@ -66,7 +68,8 @@ void VideoLowWindow::quickH264(double MBitRate)
RESOLUTIONS[RESOLUTION_IDX::RESOLUTION_AS_INPUT],
CODECS[CODEC_IDX::H264],
ui->HardwareAccelerationQuickComboBox->currentIndex(),
FRAMERATES[ui->FramerateQuickComboBox->currentIndex()]
FRAMERATES[ui->FramerateQuickComboBox->currentIndex()],
false
),
ui->HardwareAccelerationQuickComboBox->currentIndex() != 0
);
Expand All @@ -83,7 +86,8 @@ void VideoLowWindow::quickHEVC(double MBitRate)
RESOLUTIONS[RESOLUTION_IDX::RESOLUTION_AS_INPUT],
CODECS[CODEC_IDX::HEVC],
ui->HardwareAccelerationQuickComboBox->currentIndex(),
FRAMERATES[ui->FramerateQuickComboBox->currentIndex()]
FRAMERATES[ui->FramerateQuickComboBox->currentIndex()],
false
),
ui->HardwareAccelerationQuickComboBox->currentIndex() != 0
);
Expand Down Expand Up @@ -168,7 +172,8 @@ void VideoLowWindow::exportVideo()
RESOLUTIONS[ui->ResolutionComboBox->currentIndex()],
CODECS[ui->CodecComboBox->currentIndex()],
ui->HardwareAccelerationComboBox->currentIndex(),
FRAMERATES[ui->FramerateComboBox->currentIndex()]
FRAMERATES[ui->FramerateComboBox->currentIndex()],
false
),
ui->HardwareAccelerationComboBox->currentIndex() != 0
);
Expand All @@ -183,6 +188,26 @@ void VideoLowWindow::reviewVideo()
cutWindow->show();
}

void VideoLowWindow::quickTrimOnly()
{
if (currentVideo) {
handleExportExitCode(
ffmpeg.exportFile(
*currentVideo,
getTrimSettings(),
ui->BitrateDoubleSpinBox->value(),
RESOLUTIONS[RESOLUTION_IDX::RESOLUTION_AS_INPUT],
CODECS[CODEC_IDX::H264],
ui->HardwareAccelerationQuickComboBox->currentIndex(),
FRAMERATES[0],
true
),
ui->HardwareAccelerationQuickComboBox->currentIndex() != 0
);

}
}

void VideoLowWindow::gotCutInformation(QTime start, QTime end, bool cancelled)
{
if (!cancelled) {
Expand Down
21 changes: 17 additions & 4 deletions src/videolowwindow.ui
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>777</width>
<height>642</height>
<width>776</width>
<height>655</height>
</rect>
</property>
<property name="sizePolicy">
Expand All @@ -20,6 +20,12 @@
<string>VideoLow</string>
</property>
<widget class="QWidget" name="centralwidget">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<widget class="QWidget" name="verticalLayoutWidget">
<property name="geometry">
<rect>
Expand Down Expand Up @@ -505,6 +511,13 @@
</item>
</layout>
</item>
<item>
<widget class="QPushButton" name="trimVideoButton">
<property name="text">
<string>Only Trim Video</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="ErrorLabel">
<property name="palette">
Expand Down Expand Up @@ -731,8 +744,8 @@
<rect>
<x>0</x>
<y>0</y>
<width>777</width>
<height>22</height>
<width>776</width>
<height>17</height>
</rect>
</property>
</widget>
Expand Down

0 comments on commit 1cd7f60

Please sign in to comment.