diff --git a/app/src/main/assets/yt_dlp_plugins/burnsubs/yt_dlp_plugins/postprocessor/burnsubs.py b/app/src/main/assets/yt_dlp_plugins/burnsubs/yt_dlp_plugins/postprocessor/burnsubs.py
index 08f4eba1..eab2d7ed 100644
--- a/app/src/main/assets/yt_dlp_plugins/burnsubs/yt_dlp_plugins/postprocessor/burnsubs.py
+++ b/app/src/main/assets/yt_dlp_plugins/burnsubs/yt_dlp_plugins/postprocessor/burnsubs.py
@@ -4,6 +4,10 @@ import tempfile
from yt_dlp.postprocessor.ffmpeg import FFmpegPostProcessor
class BurnSubsPP(FFmpegPostProcessor):
+ def __init__(self, downloader=None, preset=None):
+ super().__init__(downloader)
+ self.preset = preset
+
def run(self, info):
subs = info.get('requested_subtitles') or {}
@@ -32,17 +36,14 @@ class BurnSubsPP(FFmpegPostProcessor):
# Basic filter string; drop fixed /system/fonts to avoid Android OS permission crashes
vf_filter = f"subtitles='{esc_sub}'"
+ opts = ['-vf', vf_filter, '-c:v', 'libx264']
+
+ if self.preset and str(self.preset).strip():
+ opts.extend(['-preset', str(self.preset).strip()])
+
+ opts.extend(['-crf', '20', '-c:a', 'copy'])
- self.run_ffmpeg_multiple_files(
- [path], temp_out,
- [
- '-vf', vf_filter,
- '-c:v', 'libx264',
- '-preset', 'ultrafast',
- '-crf', '20',
- '-c:a', 'copy'
- ]
- )
+ self.run_ffmpeg_multiple_files([path], temp_out, opts)
os.replace(temp_out, path)
info['filepath'] = path
diff --git a/app/src/main/assets/yt_dlp_plugins/compatiblerecoder/yt_dlp_plugins/postprocessor/compatiblerecoder.py b/app/src/main/assets/yt_dlp_plugins/compatiblerecoder/yt_dlp_plugins/postprocessor/compatiblerecoder.py
index 9121718b..43cfae3f 100644
--- a/app/src/main/assets/yt_dlp_plugins/compatiblerecoder/yt_dlp_plugins/postprocessor/compatiblerecoder.py
+++ b/app/src/main/assets/yt_dlp_plugins/compatiblerecoder/yt_dlp_plugins/postprocessor/compatiblerecoder.py
@@ -51,6 +51,10 @@ class CompatibleRecoderPP(FFmpegPostProcessor):
'png',
}
+ def __init__(self, downloader=None, preset=None):
+ super().__init__(downloader)
+ self.preset = str(preset).strip() if preset and str(preset).strip() else None
+
def _stream_codec(self, stream):
"""Return the codec name and codec tag as lowercase strings."""
codec_name = (stream.get('codec_name') or '').lower()
@@ -238,6 +242,13 @@ class CompatibleRecoderPP(FFmpegPostProcessor):
codec,
]
+ # Apply preset to x264 re-encodes (omit if copying or no preset provided)
+ if codec == 'libx264' and self.preset:
+ options += [
+ f'-preset:{video_index}',
+ self.preset,
+ ]
+
# Preserve an already embedded thumbnail as cover art.
if item['attached_pic']:
options += [
diff --git a/app/src/main/java/com/deniscerri/ytdl/MainActivity.kt b/app/src/main/java/com/deniscerri/ytdl/MainActivity.kt
index 1f3d08a8..f9b26ca7 100644
--- a/app/src/main/java/com/deniscerri/ytdl/MainActivity.kt
+++ b/app/src/main/java/com/deniscerri/ytdl/MainActivity.kt
@@ -60,6 +60,7 @@ import com.deniscerri.ytdl.ui.downloads.DownloadQueueMainFragment
import com.deniscerri.ytdl.ui.downloads.HistoryFragment
import com.deniscerri.ytdl.ui.more.settings.SettingsActivity
import com.deniscerri.ytdl.util.ApkInstallUtil
+import com.deniscerri.ytdl.util.BgUtilsPoTokenGeneratorUtil
import com.deniscerri.ytdl.util.CrashListener
import com.deniscerri.ytdl.util.NavbarUtil
import com.deniscerri.ytdl.util.NavbarUtil.applyNavBarStyle
@@ -238,6 +239,13 @@ class MainActivity : BaseActivity() {
setupWithNavController(navController)
//terminate button
menu.getItem(8).setOnMenuItemClickListener {
+ fun terminateApp() {
+ BgUtilsPoTokenGeneratorUtil.releaseServer(context, 0)
+ finishAndRemoveTask()
+ finishAffinity()
+ exitProcess(0)
+ }
+
if (preferences.getBoolean("ask_terminate_app", true)){
var doNotShowAgain = false
val terminateDialog = MaterialAlertDialogBuilder(this@MainActivity)
@@ -264,16 +272,13 @@ class MainActivity : BaseActivity() {
if (doNotShowAgain){
preferences.edit().putBoolean("ask_terminate_app", false).apply()
}
- finishAndRemoveTask()
- finishAffinity()
- exitProcess(0)
+ terminateApp()
}
}
}
terminateDialog.show()
}else{
- finishAndRemoveTask()
- exitProcess(0)
+ terminateApp()
}
true
}
diff --git a/app/src/main/java/com/deniscerri/ytdl/util/extractors/ytdlp/YTDLPUtil.kt b/app/src/main/java/com/deniscerri/ytdl/util/extractors/ytdlp/YTDLPUtil.kt
index 4d22976f..a86ad18d 100644
--- a/app/src/main/java/com/deniscerri/ytdl/util/extractors/ytdlp/YTDLPUtil.kt
+++ b/app/src/main/java/com/deniscerri/ytdl/util/extractors/ytdlp/YTDLPUtil.kt
@@ -1138,6 +1138,8 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
request.addOption("--download-archive", FileUtil.getDownloadArchivePath(context))
}
+ val internalPluginFFmpegPreset = sharedPreferences.getString("internal_plugin_ffmpeg_preset", "")
+
val preferredAudioCodec = sharedPreferences.getString("audio_codec", "")!!
val aCodecPrefIndex = context.getStringArray(R.array.audio_codec_values).indexOf(preferredAudioCodec)
var aCodecPref = runCatching { context.getStringArray(R.array.audio_codec_values_ytdlp)[aCodecPrefIndex] }.getOrElse { "" }
@@ -1322,6 +1324,34 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
metadataCommands.add("--embed-metadata")
}
+ if (downloadItem.videoPreferences.writeSubs){
+ request.addOption("--write-subs")
+ }
+
+ if(downloadItem.videoPreferences.writeAutoSubs){
+ request.addOption("--write-auto-subs")
+ }
+
+ if (downloadItem.videoPreferences.embedSubs) {
+ if (sharedPreferences.getBoolean("no_keep_subs", false) && (downloadItem.videoPreferences.writeSubs || downloadItem.videoPreferences.writeAutoSubs)) {
+ request.addOption("--compat-options", "no-keep-subs")
+ }
+
+ request.addOption("--embed-subs")
+ }
+
+ if (downloadItem.videoPreferences.embedSubs || downloadItem.videoPreferences.writeSubs || downloadItem.videoPreferences.writeAutoSubs){
+ val subFormat = sharedPreferences.getString("sub_format", "")
+ if(subFormat!!.isNotBlank()){
+ request.addOption("--sub-format", "${subFormat}/best")
+ request.addOption("--convert-subtitles", subFormat)
+ }
+ request.addOption("--sub-langs", downloadItem.videoPreferences.subsLanguages.ifEmpty { ".*-orig" })
+ }
+
+ if (downloadItem.videoPreferences.burnSubs) {
+ request.addOption("--use-postprocessor", "BurnSubs:when=after_move;preset=$internalPluginFFmpegPreset")
+ }
var cont = ""
val outputContainer = downloadItem.container
@@ -1390,7 +1420,7 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
if (downloadItem.videoPreferences.compatibilityMode) {
request.addOption("--merge-output-format", "mp4")
request.addOption("--remux-video", "mp4")
- request.addOption("--use-postprocessor", "CompatibleRecoder")
+ request.addOption("--use-postprocessor", "CompatibleRecoder:preset=$internalPluginFFmpegPreset")
vCodecPref = "h264"
aCodecPref = "aac"
}
@@ -1563,37 +1593,6 @@ class YTDLPUtil(private val context: Context, private val commandTemplateDao: Co
request.addOption("-f", f.toString().replace("/$".toRegex(), ""))
- if (downloadItem.videoPreferences.writeSubs){
- request.addOption("--write-subs")
- }
-
- if(downloadItem.videoPreferences.writeAutoSubs){
- request.addOption("--write-auto-subs")
- }
-
-
-
- if (downloadItem.videoPreferences.embedSubs) {
- if (sharedPreferences.getBoolean("no_keep_subs", false) && (downloadItem.videoPreferences.writeSubs || downloadItem.videoPreferences.writeAutoSubs)) {
- request.addOption("--compat-options", "no-keep-subs")
- }
-
- request.addOption("--embed-subs")
- }
-
- if (downloadItem.videoPreferences.embedSubs || downloadItem.videoPreferences.writeSubs || downloadItem.videoPreferences.writeAutoSubs){
- val subFormat = sharedPreferences.getString("sub_format", "")
- if(subFormat!!.isNotBlank()){
- request.addOption("--sub-format", "${subFormat}/best")
- request.addOption("--convert-subtitles", subFormat)
- }
- request.addOption("--sub-langs", downloadItem.videoPreferences.subsLanguages.ifEmpty { ".*-orig" })
- }
-
- if (downloadItem.videoPreferences.burnSubs) {
- request.addOption("--use-postprocessor", "BurnSubs:when=after_move")
- }
-
var copyStream = ""
if (downloadItem.videoPreferences.cropValues.isNotBlank()){
diff --git a/app/src/main/res/drawable/baseline_fast_forward_24.xml b/app/src/main/res/drawable/baseline_fast_forward_24.xml
new file mode 100644
index 00000000..b2b02e17
--- /dev/null
+++ b/app/src/main/res/drawable/baseline_fast_forward_24.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/values/arrays.xml b/app/src/main/res/values/arrays.xml
index 940c43c2..0fc471d6 100644
--- a/app/src/main/res/values/arrays.xml
+++ b/app/src/main/res/values/arrays.xml
@@ -1627,4 +1627,22 @@
- external
+
+ - @string/defaultValue
+ - veryfast
+ - faster
+ - fast
+ - medium
+ - slow
+
+
+
+
+ - veryfast
+ - faster
+ - fast
+ - medium
+ - slow
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 34477a1f..e4c05f41 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -587,6 +587,8 @@
Automatically detect URLs in clipboard in the home screen
Check clipboard in the home screen
Clear infojsons
+ Internal Plugin FFmpeg Preset
+ Preset FFmpeg uses for internal plugins like burn subs etc. Adjusting this preference affects the final file size!
- Every hour
- Every %d hours
- Every day
- Every %d days
- Every week
- Every %d weeks
diff --git a/app/src/main/res/xml/processing_preferences.xml b/app/src/main/res/xml/processing_preferences.xml
index 2cfc58e2..efb59e26 100644
--- a/app/src/main/res/xml/processing_preferences.xml
+++ b/app/src/main/res/xml/processing_preferences.xml
@@ -291,6 +291,15 @@
app:summary="@string/preferred_format_id_summary"
app:title="@string/preferred_format_id" />
+
+