@@ -24,6 +24,7 @@ import com.nasahacker.convertit.util.CueParser
24
24
import com.nasahacker.convertit.domain.model.CueFile
25
25
import com.nasahacker.convertit.domain.model.CueTrack
26
26
import dagger.hilt.android.qualifiers.ApplicationContext
27
+ import kotlinx.coroutines.CompletableDeferred
27
28
import kotlinx.coroutines.Dispatchers
28
29
import kotlinx.coroutines.withContext
29
30
import java.io.File
@@ -228,6 +229,8 @@ class AudioConverterRepositoryImpl
228
229
arrayOf(
229
230
" -y" ,
230
231
" -i" , inputPath,
232
+ " -map" , " 0:a" , // Only map audio streams
233
+ " -vn" , // Disable video streams
231
234
" -ar" , " 16000" ,
232
235
" -ac" , " 1" ,
233
236
" -c:a" , AudioCodec .fromFormat(outputFormat).codec,
@@ -242,6 +245,8 @@ class AudioConverterRepositoryImpl
242
245
arrayOf(
243
246
" -y" ,
244
247
" -i" , inputPath,
248
+ " -map" , " 0:a" ,
249
+ " -vn" ,
245
250
" -c:a" , AudioCodec .fromFormat(outputFormat).codec,
246
251
" -b:a" , bitrate.bitrate,
247
252
" -application" , " voip" ,
@@ -253,6 +258,8 @@ class AudioConverterRepositoryImpl
253
258
arrayOf(
254
259
" -y" ,
255
260
" -i" , inputPath,
261
+ " -map" , " 0:a" ,
262
+ " -vn" ,
256
263
" -c:a" , AudioCodec .fromFormat(outputFormat).codec,
257
264
" -b:a" , bitrate.bitrate,
258
265
" -filter:a" , " atempo=$playbackSpeed " ,
@@ -264,6 +271,8 @@ class AudioConverterRepositoryImpl
264
271
arrayOf(
265
272
" -y" ,
266
273
" -i" , inputPath,
274
+ " -map" , " 0:a" ,
275
+ " -vn" ,
267
276
" -c:a" , AudioCodec .fromFormat(outputFormat).codec,
268
277
" -b:a" , bitrate.bitrate,
269
278
" -filter:a" , " atempo=$playbackSpeed " ,
@@ -366,18 +375,26 @@ class AudioConverterRepositoryImpl
366
375
)
367
376
368
377
try {
369
- val session = FFmpegKit .executeWithArguments(ffmpegArgs )
378
+ val sessionCompleted = CompletableDeferred < Boolean >( )
370
379
371
- if (ReturnCode .isSuccess(session.returnCode)) {
372
- outputPaths.add(outputFilePath)
373
- processedTracks++
374
-
375
- val progress = ((processedTracks.toFloat() / totalTracks) * 100 ).toInt()
376
- onProgress(progress)
377
-
378
- Log .d(TAG , " Successfully converted track ${track.trackNumber} : ${track.title} " )
379
- } else {
380
- Log .e(TAG , " Failed to convert track ${track.trackNumber} : ${session.failStackTrace} " )
380
+ FFmpegKit .executeWithArgumentsAsync(ffmpegArgs, { session ->
381
+ if (ReturnCode .isSuccess(session.returnCode)) {
382
+ outputPaths.add(outputFilePath)
383
+ processedTracks++
384
+
385
+ val progress = ((processedTracks.toFloat() / totalTracks) * 100 ).toInt()
386
+ onProgress(progress)
387
+
388
+ Log .d(TAG , " Successfully converted track ${track.trackNumber} : ${track.title} " )
389
+ sessionCompleted.complete(true )
390
+ } else {
391
+ Log .e(TAG , " Failed to convert track ${track.trackNumber} : ${session.failStackTrace} " )
392
+ sessionCompleted.complete(false )
393
+ }
394
+ })
395
+
396
+ val success = sessionCompleted.await()
397
+ if (! success) {
381
398
onFailure(" Failed to convert track ${track.trackNumber} : ${track.title} " )
382
399
tempAudioFile.delete()
383
400
return
@@ -407,32 +424,11 @@ class AudioConverterRepositoryImpl
407
424
408
425
private fun findCueFileForUri (audioUri : Uri ): File ? {
409
426
try {
410
-
411
427
val fileName = getFileName(context.contentResolver, audioUri)
412
- val fileNameWithoutExt = fileName.substringBeforeLast(" ." )
413
428
val isFlac = fileName.endsWith(" .flac" , ignoreCase = true )
414
429
415
-
416
- val possibleLocations = listOf (
417
- context.getExternalFilesDir(null ),
418
- context.filesDir,
419
- File (" /storage/emulated/0/Download" ),
420
- File (" /storage/emulated/0/Music" )
421
- )
422
-
423
-
424
- for (dir in possibleLocations) {
425
- if (dir?.exists() == true ) {
426
- val cueFile = File (dir, " $fileNameWithoutExt .cue" )
427
- if (cueFile.exists()) {
428
- return cueFile
429
- }
430
- }
431
- }
432
-
433
-
430
+ // Only check for embedded CUE in FLAC files since external CUE files are selected via file picker
434
431
if (isFlac) {
435
-
436
432
context.contentResolver.openInputStream(audioUri)?.use { inputStream ->
437
433
val tempFlacFile = File (context.cacheDir, " temp_flac_${System .currentTimeMillis()} .flac" )
438
434
FileOutputStream (tempFlacFile).use { outputStream ->
@@ -469,6 +465,8 @@ class AudioConverterRepositoryImpl
469
465
args.addAll(arrayOf(" -y" , " -i" , inputPath))
470
466
471
467
468
+ args.addAll(arrayOf(" -map" , " 0:a" , " -vn" ))
469
+
472
470
args.addAll(arrayOf(" -ss" , CueParser .formatSecondsForFFmpeg(track.startTimeSeconds)))
473
471
474
472
@@ -508,9 +506,18 @@ class AudioConverterRepositoryImpl
508
506
}
509
507
510
508
private fun sanitizeFileName (fileName : String ): String {
511
- return fileName.replace(Regex (" [^a-zA-Z0-9._\\ -\\ s]" ), " _" )
509
+ val invalidChars = Regex (" [<>:\" /\\\\ |?*\\ x00-\\ x1f]" )
510
+ val sanitized = fileName.replace(invalidChars, " _" )
512
511
.replace(Regex (" \\ s+" ), " " )
513
512
.trim()
513
+ .trimEnd(' .' )
514
+
515
+ val maxLength = 200
516
+ return if (sanitized.length > maxLength) {
517
+ sanitized.substring(0 , maxLength).trimEnd()
518
+ } else {
519
+ sanitized
520
+ }.ifEmpty { " Track" }
514
521
}
515
522
516
523
override suspend fun convertWithManualCue (
0 commit comments