13#include <QRegularExpression>
16#include <QJsonDocument>
21const QString keyAnimationExport =
"ANIMATION_EXPORT";
23const QString keyFfmpegPath =
"ffmpeg_path";
24const QString keyVideoDirectory =
"recorder_export/videodirectory";
26const QString keyInputFps =
"recorder_export/inputfps";
27const QString keyFps =
"recorder_export/fps";
28const QString keyResultPreview=
"recorder_export/resultpreview";
29const QString keyFirstFrameSec =
"recorder_export/firstframesec";
30const QString keyExtendResult =
"recorder_export/extendresult";
31const QString keyLastFrameSec =
"recorder_export/lastframesec";
32const QString keyResize =
"recorder_export/resize";
33const QString keySize =
"recorder_export/size";
34const QString keyLockRatio =
"recorder_export/lockratio";
35const QString keyLockFps =
"recorder_export/lockfps";
37const QString keySelectedFormat =
"recorder_export/selectedformat";
38const QString keyFormatPreferences =
"recorder_export/formatpreferences";
40const QString keyProfileIndex =
"recorder_export/profileIndex";
41const QString keyProfiles =
"recorder_export/profiles";
42const QString keyEditedProfiles =
"recorder_export/editedprofiles";
44const QString profilePrefix =
"-reinit_filter 0\n-framerate $IN_FPS\n-i \"$INPUT_DIR%07d.$EXT\"\n-framerate $OUT_FPS\n-start_number $FRAMES-1\n-i \"$INPUT_DIR%07d.$EXT\"\n";
47 {
"MP4 x264",
"mp4", profilePrefix %
"-filter_complex \"\n"
55 " [1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))'[hold1];\n"
56 " [hold1]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2[hold2];\n"
57 " [hold2]setsar=1:1[hold3];\n"
58 " [hold3]split=3[preview1][transition1][end1];\n"
60 " [preview1]tpad=stop_mode=clone:stop_duration=$FIRST_FRAME_SEC[preview2];\n"
61 " [preview2]setpts=PTS-STARTPTS[preview3];\n"
63 " [transition1]tpad=stop_mode=clone:stop_duration=$TRANSITION_LENGTH[transition2];\n"
64 " [transition2]setpts=PTS-STARTPTS[transition3];\n"
65 " [transition3]framerate=$OUT_FPS[transition4];\n"
67 " [0]fps=$OUT_FPS[main1];\n"
68 " [main1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))':eval=frame[main2];\n"
69 " [main2]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2:eval=frame[main3];\n"
70 " [main3]setsar=1:1[main4];\n"
71 " [transition4][main4]xfade=transition=smoothright:duration=$TRANSITION_LENGTH:offset=0[main5];\n"
73 " [end1]tpad=stop_mode=clone:stop_duration=$LAST_FRAME_SEC[end2];\n"
74 " [end2]setpts=PTS-STARTPTS[end3];\n"
76 " [preview3][main5][end3]concat=n=3:v=1:a=0[final1];\n"
77 " [final1]setpts=PTS-STARTPTS\n"
79 "\"\n-stats\n-loglevel error\n-c:v $H264_ENCODER\n-r $OUT_FPS\n-pix_fmt yuv420p" },
80 {
"GIF",
"gif", profilePrefix %
"-filter_complex \"\n"
81 " [1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))'[hold1];\n"
82 " [hold1]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2[hold2];\n"
83 " [hold2]setsar=1:1[hold3];\n"
84 " [hold3]split=3[preview1][transition1][end1];\n"
86 " [preview1]tpad=stop_mode=clone:stop_duration=$FIRST_FRAME_SEC[preview2];\n"
87 " [preview2]setpts=PTS-STARTPTS[preview3];\n"
89 " [transition1]tpad=stop_mode=clone:stop_duration=$TRANSITION_LENGTH[transition2];\n"
90 " [transition2]setpts=PTS-STARTPTS[transition3];\n"
91 " [transition3]framerate=$OUT_FPS[transition4];\n"
93 " [0]fps=$OUT_FPS[main1];\n"
94 " [main1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))':eval=frame[main2];\n"
95 " [main2]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2:eval=frame[main3];\n"
96 " [main3]setsar=1:1[main4];\n"
97 " [transition4][main4]xfade=transition=smoothright:duration=$TRANSITION_LENGTH:offset=0[main5];\n"
99 " [end1]tpad=stop_mode=clone:stop_duration=$LAST_FRAME_SEC[end2];\n"
100 " [end2]setpts=PTS-STARTPTS[end3];\n"
102 " [preview3][main5][end3]concat=n=3:v=1:a=0[final1];\n"
103 " [final1]setpts=PTS-STARTPTS[final2];\n"
104 " [final2]split[final3][final4];\n"
105 " [final3]palettegen[palettegen];\n"
106 " [final4][palettegen]paletteuse\n"
107 "\"\n-stats\n-loglevel error\n-r $OUT_FPS" },
108 {
"Matroska",
"mkv", profilePrefix %
"-filter_complex \"\n"
109 " [1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))'[hold1];\n"
110 " [hold1]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2[hold2];\n"
111 " [hold2]setsar=1:1[hold3];\n"
112 " [hold3]split=3[preview1][transition1][end1];\n"
114 " [preview1]tpad=stop_mode=clone:stop_duration=$FIRST_FRAME_SEC[preview2];\n"
115 " [preview2]setpts=PTS-STARTPTS[preview3];\n"
117 " [transition1]tpad=stop_mode=clone:stop_duration=$TRANSITION_LENGTH[transition2];\n"
118 " [transition2]setpts=PTS-STARTPTS[transition3];\n"
119 " [transition3]framerate=$OUT_FPS[transition4];\n"
121 " [0]fps=$OUT_FPS[main1];\n"
122 " [main1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))':eval=frame[main2];\n"
123 " [main2]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2:eval=frame[main3];\n"
124 " [main3]setsar=1:1[main4];\n"
125 " [transition4][main4]xfade=transition=smoothright:duration=$TRANSITION_LENGTH:offset=0[main5];\n"
127 " [end1]tpad=stop_mode=clone:stop_duration=$LAST_FRAME_SEC[end2];\n"
128 " [end2]setpts=PTS-STARTPTS[end3];\n"
130 " [preview3][main5][end3]concat=n=3:v=1:a=0[final1];\n"
131 " [final1]setpts=PTS-STARTPTS\n"
132 "\"\n-stats\n-loglevel error\n-pix_fmt yuv420p\n-r $OUT_FPS" },
133 {
"WebM",
"webm", profilePrefix %
"-filter_complex \"\n"
134 " [1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))'[hold1];\n"
135 " [hold1]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2[hold2];\n"
136 " [hold2]setsar=1:1[hold3];\n"
137 " [hold3]split=3[preview1][transition1][end1];\n"
139 " [preview1]tpad=stop_mode=clone:stop_duration=$FIRST_FRAME_SEC[preview2];\n"
140 " [preview2]setpts=PTS-STARTPTS[preview3];\n"
142 " [transition1]tpad=stop_mode=clone:stop_duration=$TRANSITION_LENGTH[transition2];\n"
143 " [transition2]setpts=PTS-STARTPTS[transition3];\n"
144 " [transition3]framerate=$OUT_FPS[transition4];\n"
146 " [0]fps=$OUT_FPS[main1];\n"
147 " [main1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))':eval=frame[main2];\n"
148 " [main2]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2:eval=frame[main3];\n"
149 " [main3]setsar=1:1[main4];\n"
150 " [transition4][main4]xfade=transition=smoothright:duration=$TRANSITION_LENGTH:offset=0[main5];\n"
152 " [end1]tpad=stop_mode=clone:stop_duration=$LAST_FRAME_SEC[end2];\n"
153 " [end2]setpts=PTS-STARTPTS[end3];\n"
155 " [preview3][main5][end3]concat=n=3:v=1:a=0[final1];\n"
156 " [final1]setpts=PTS-STARTPTS\n"
157 "\"\n-stats\n-loglevel error\n-r $OUT_FPS" },
158 {
"MP4 x264 (Flash Effect)",
"mp4", profilePrefix %
"-filter_complex \"\n"
159 " [1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))'[hold1];\n"
160 " [hold1]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2[hold2];\n"
161 " [hold2]setsar=1:1[hold3];\n"
162 " [hold3]split=3[preview1][fade1][end1];\n"
164 " [preview1]tpad=stop_mode=clone:stop_duration=$FIRST_FRAME_SEC[preview2];\n"
165 " [preview2]setpts=PTS-STARTPTS[preview3];\n"
167 " [fade1]tpad=stop_mode=clone:stop_duration=$TRANSITION_LENGTH[fade2];\n"
168 " [fade2]setpts=PTS-STARTPTS[fade3];\n"
169 " [fade3]fade=out:duration=$TRANSITION_LENGTH:color=white[fade4];\n"
171 " [0]fps=$OUT_FPS[main1];\n"
172 " [main1]scale='min($WIDTH, iw*($HEIGHT/ih))':'min($HEIGHT, ih*($WIDTH/iw))':eval=frame[main2];\n"
173 " [main2]pad=$WIDTH:$HEIGHT:(ow-iw)/2:(oh-ih)/2:eval=frame[main3];\n"
174 " [main3]setsar=1:1[main4];\n"
175 " [fade4][main4]concat[main5];\n"
177 " [end1]tpad=stop_mode=clone:stop_duration=$LAST_FRAME_SEC[end2];\n"
178 " [end2]setpts=PTS-STARTPTS[end3];\n"
180 " [preview3][main5][end3]concat=n=3:v=1:a=0[final1];\n"
181 " [final1]setpts=PTS-STARTPTS\n"
182 "\"\n-stats\n-loglevel error\n-c:v $H264_ENCODER\n-r $OUT_FPS\n-pix_fmt yuv420p" },
183 {
"Custom1",
"editme", profilePrefix %
"-filter_complex \"loop=$LAST_FRAME_SEC:size=1:start=$FRAMES,scale=$WIDTH:$HEIGHT\"\n-r $OUT_FPS" },
184 {
"Custom2",
"editme", profilePrefix %
"-filter_complex \"loop=$LAST_FRAME_SEC:size=1:start=$FRAMES,scale=$WIDTH:$HEIGHT\"\n-r $OUT_FPS" },
185 {
"Custom3",
"editme", profilePrefix %
"-filter_complex \"loop=$LAST_FRAME_SEC:size=1:start=$FRAMES,scale=$WIDTH:$HEIGHT\"\n-r $OUT_FPS" },
186 {
"Custom4",
"editme", profilePrefix %
"-filter_complex \"loop=$LAST_FRAME_SEC:size=1:start=$FRAMES,scale=$WIDTH:$HEIGHT\"\n-r $OUT_FPS" }
213 settings->selectedFormat = selectedFormat();
214 settings->formatPreferences = formatPreferences();
331QString RecorderExportConfig::selectedFormat()
const
336void RecorderExportConfig::setSelectedFormat(
const QString &
value)
341QVariantMap RecorderExportConfig::formatPreferences()
const
343 QByteArray bytes =
config->
readEntry(keyFormatPreferences, QByteArray());
344 if (!bytes.isEmpty()) {
345 QJsonDocument doc = QJsonDocument::fromJson(bytes);
346 if (doc.isObject()) {
347 return doc.toVariant().toMap();
350 return QVariantMap();
353void RecorderExportConfig::setFormatPreferences(
const QVariantMap &
value)
355 config->
writeEntry(keyFormatPreferences, QJsonDocument::fromVariant(
value).toJson(QJsonDocument::Compact));
370 const QString &profilesStr =
config->
readEntry(keyProfiles, QString());
371 if (profilesStr.isEmpty())
372 return ::defaultProfiles;
376 const QStringList &profilesList = profilesStr.split(
"\n");
378 for (
const QString &profileStr : profilesList) {
381 const QStringList& profileList = profileStr.split(
"|");
382 if (profileList.size() == 3) {
383 profiles.append({profileList[0], profileList[1], QString(profileList[2]).replace(
"\\n",
"\n")});
402 const QRegularExpression cleanUp(
"[\n|]");
406 if (profile != defaultProfile) {
412 outValue += QString(profile.name).replace(cleanUp,
" ") %
"|"
413 % QString(profile.extension).replace(cleanUp,
" ") %
"|"
414 % QString(profile.arguments).replace(
"\n",
"\\n").replace(
"|",
" ") %
"\n";
428 return ::defaultProfiles;
433 const QVariantList &readValue =
config->
readEntry(keyEditedProfiles, QVariantList());
435 for (
const QVariant &item : readValue) {
436 result.insert(item.toInt());
443 QVariantList writeValue;
444 for (
int index :
value) {
445 writeValue.append(index);
482 return !(left == right);
float value(const T *src, size_t ch)
void setFFMpegLocation(const QString &value)
void writeEntry(const QString &name, const T &value)
QString ffmpegLocation(bool defaultValue=false) const
T readEntry(const QString &name, const T &defaultValue=T())
void setFirstFrameSec(int value)
void setProfiles(const QList< RecorderProfile > &value)
void setLockFps(bool value)
void setVideoDirectory(const QString &value)
void setResize(bool value)
QString ffmpegPath() const
void setLockRatio(bool value)
void loadConfiguration(RecorderExportSettings *settings, bool loadLockFps=true) const
void setResultPreview(bool value)
int firstFrameSec() const
RecorderExportConfig(bool readOnly)
bool resultPreview() const
void setInputFps(int value)
void setFfmpegPath(const QString &value)
QString videoDirectory() const
QList< RecorderProfile > defaultProfiles() const
QSet< int > editedProfilesIndexes() const
QList< RecorderProfile > profiles() const
void setProfileIndex(int value)
void setSize(const QSize &value)
void setExtendResult(bool value)
void setLastFrameSec(int value)
bool extendResult() const
void setEditedProfilesIndexes(const QSet< int > &value)
bool operator!=(const RecorderProfile &left, const RecorderProfile &right)
bool operator==(const RecorderProfile &left, const RecorderProfile &right)
QList< RecorderProfile > profiles
QList< RecorderProfile > defaultProfiles