import java.io.File
import kotlin.time.measureTime
fun main() {
val srcDir = "X:\\Movies"
val dstDir = "Z:\\Movies2"
val total = File(srcDir).walk().filter { it.isFile }.count()
var count = 0
File(srcDir).walk()
.filter { it.isFile }
.forEach {
"start process $it".logi()
try {
val time = measureTime {
val src = it
val dst = File(it.absolutePath.replace(srcDir, dstDir)).alsoParentMkdirs()
if (it.extension.lowercase() in listOf("mp4", "mkv", "wmv", "m4v", "avi", "mov", "mts")) {
val output = dst.absolutePath.replace(dst.extension, "mp4")
if (File(output).exists()) {
"file exists $output".logi()
return@measureTime
}
ffmpegCov(src.absolutePath, output)
} else {
if (dst.exists()) {
"file exists $dst".logi()
return@measureTime
}
src.copyTo(dst, bufferSize = 1 * 1024 * 1024)
}
}
"${++count}/$total use time $time end process $it".logi()
} catch (e: Exception) {
"failed process $it".loge()
e.printStackTrace()
}
}
}
fun ffmpegCov(input: String, output: String) {
val cmd = listOf(
"cmd", "/c",
"ffmpeg", "-hide_banner", "-loglevel", "warning", "-stats",
"-hwaccel", "cuda", "-hwaccel_output_format", "cuda",
"-i", input.wrap(),
"-c:v", "av1_nvenc", "-cq", "36", "-preset", "p4",
// "-c:a", "copy",
output.wrap()
)
exec(cmd).waitFor()
}
fun exec(cmd: List<String>) = ProcessBuilder().apply {
command(*cmd.toTypedArray())
inheritIO()
}.start()
fun String.wrap() = "\"$this\""
fun File.alsoParentMkdirs() = also {
if (it.parentFile?.exists() != true) it.parentFile?.mkdirs()
}
fun <T> T.logi() = also(::println)
fun <T> T.loge() = also(System.err::println)
质量对比
SSIM:
ffmpeg -i video1.mp4 -i video2.mp4 -lavfi ssim="stats_file=ssim.log" -f null -
VMAF:
ffmpeg -i "对比视频" -i "源视频" -filter_complex "[0:v][1:v]libvmaf=model=version=vmaf_v0.6.1:log_path='C\:\\Users\\litte\\Desktop\\vmaf_log.txt':n_threads=99" -f null -