Last active
June 23, 2023 03:47
-
-
Save Aquei/c463dafbd85999fe419fc7f8860a8292 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#license CC0 - https://creativecommons.org/publicdomain/zero/1.0/deed.ja | |
$noise_max = "-30dB" #この音量未満を対象とする | |
$duration_min = "1" #この長さ(秒)以上を対象とする | |
$silent_start_min = 2.0 #開始からこの秒数以内に始まった無音をイントロ無音の対象とする | |
$silent_end_max = 2.0 #末尾からこの秒数以内に始まった無音をアウトロ無音の対象とする | |
if ($args.Length -eq 0){ | |
throw "need at least one file path" | |
} | |
function Get-SCSilenceData{ | |
param ( | |
$start, | |
$end | |
) | |
$start_time = $start | select-string -Pattern 'silence_start: ([0-9.]+)' | %{ $_.Matches.Groups[1].value } | |
$end_time = $end | select-string -Pattern 'silence_end: ([0-9.]+)' | %{ $_.Matches.Groups[1].value } | |
[float] $start_time, [float] $end_time | |
} | |
function ConvertTo-SCDurationInt{ | |
param( | |
$duration_str | |
) | |
$nums = $duration_str -Split ':' | |
[array]::Reverse($nums) | |
$duration = 0 | |
0..($nums.Length -1) | foreach { | |
$co = [Math]::Pow(60, $_) | |
$duration = $duration + $co * $nums[$_] | |
} | |
return $duration | |
} | |
function Remove-SCSilence{ | |
param( | |
$file, | |
$start = 0, | |
$end = 0 | |
) | |
$orig_path = $file | |
$resolved_orig_path = $orig_path | %{ resolve-path -LiteralPath $_ } | |
$resolved_orig_parent = $resolved_orig_path | %{ split-path -LiteralPath $_ } | |
$ext = $orig_path -Split '\.' | select-object -Last 1 | |
foreach($c in 0..1000){ | |
$temp_filename = [string] (Get-Date|%{$_.Ticks}) + ".${ext}" | |
$temp = $resolved_orig_parent + '\' + $temp_filename | |
if (test-path -Path $temp) { | |
start-sleep -Milliseconds 10 | |
continue | |
} | |
break | |
} | |
#元ファイルを一時的に名前に変更 | |
rename-item -LiteralPath $resolved_orig_path -NewName $temp_filename | |
#cut | |
if ($start) { | |
$ss = "-ss", $start | |
} else { | |
$ss = $() | |
} | |
if ($end) { | |
$to = "-to", $end | |
}else{ | |
$to = @() | |
} | |
ffmpeg "-hide_banner" "-loglevel" "error" "-i" $temp "-codec" "copy" @ss @to $resolved_orig_path | |
$result = $? | |
if($result -eq $true){ | |
remove-item -Path $temp | |
} | |
} | |
function Get-SCTargetData{ | |
param ( | |
$file | |
) | |
try{ | |
$rawdata = ffmpeg "-hide_banner" "-i" "$file" "-af" "silencedetect=noise=${noise_max}:duration=${duration_min}" "-f" "null" "-" 2>&1 | |
} catch { | |
Write-Output $_ | |
} | |
$duration_str = $rawdata | select-string -Pattern 'Duration: (\d{2}:\d{2}:\d{2}\.\d+)' | %{ $_.Matches.Groups[1].value } | |
$duration = ConvertTo-SCDurationInt $duration_str | |
$silences = $rawdata | select-string -Pattern '^\[silencedetect' | |
if ($silences.Length % 2 -ne 0){ | |
throw "something weard" | |
} | |
#初期化 | |
$remove_intro = $false | |
$remove_outro = $false | |
if ($silences.Length -ge 2) { | |
#少なくとも一つの無音がある | |
$silence_data = Get-SCSilenceData $silences[0].Line $silences[1].Line | |
$start_first_silence = $silence_data[0] | |
$end_first_silence = $silence_data[1] | |
if ($start_first_silence -le $silent_start_min){ | |
#最初の無音がファイルの開始指定秒以内に始まっている場合 | |
write-verbose "先頭の無音が${start_first_silence}に始まり、${end_first_silence}に終わりました" | |
$remove_intro = $end_first_silence | |
} | |
if ($silences.Length -ge 4){ | |
#複数の無音がある | |
#最後の無音を調べる | |
$last_silence_data = Get-SCSilenceData $silences[-2].Line $silences[-1].Line | |
$start_last_silence = $last_silence_data[0] | |
$end_last_silence = $last_silence_data[1] | |
}else{ | |
#無音は一つしかなかった場合 | |
$start_last_silence = $start_first_silence | |
$end_last_silence = $end_first_silence | |
if (($start_last_silence -le $silent_start_min) -and (($duration - $start_last_silence) -ge $silent_end_max)){ | |
#このファイルはほとんど無音? | |
} | |
} | |
if (($duration - $end_last_silence) -le $silent_end_max){ | |
#最後の無音がファイルの終了から指定秒以前に終了した | |
write-verbose "末尾の無音が${start_last_silence}に始まり、${end_last_silence}に終わりました" | |
$remove_outro = $start_last_silence | |
} | |
return $remove_intro, $remove_outro | |
} | |
} | |
foreach ($target in $args){ | |
if (test-path -LiteralPath $target){ | |
$remove_intro, $remove_outro = Get-SCTargetData $target $end_first_silence | |
if ($remove_intro -or $remove_outro){ | |
Remove-SCSilence $target $remove_intro $remove_outro | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment