긴 비디오를 검은 색 장면으로 작은 장으로 나누는 두 가지 PowerShell 스크립트는 다음과 같습니다.
Detect_black.ps1 및 Cut_black.ps1로 저장하십시오. Windows 용 ffmpeg를 다운로드 하고 옵션 섹션에서 ffmpeg.exe 및 비디오 폴더의 경로를 스크립트에 알려주십시오.
두 스크립트 모두 기존 비디오 파일을 건드리지 않고 그대로 유지됩니다.
그러나 입력 비디오가있는 곳에서 몇 개의 새로운 파일을 얻게됩니다.
- 사용 된 ffmpeg 명령 모두에 대한 콘솔 출력이있는 비디오 당 로그 파일
- 수동 미세 조정을위한 모든 검은 색 장면의 타임 스탬프가있는 비디오 당 CSV 파일
- 이전에 감지 된 검은 장면 수에 따른 몇 가지 새로운 비디오
실행할 첫 스크립트 : Detect_black.ps1
### Options __________________________________________________________________________________________________________
$ffmpeg = ".\ffmpeg.exe" # Set path to your ffmpeg.exe; Build Version: git-45581ed (2014-02-16)
$folder = ".\Videos\*" # Set path to your video folder; '\*' must be appended
$filter = @("*.mov","*.mp4") # Set which file extensions should be processed
$dur = 4 # Set the minimum detected black duration (in seconds)
$pic = 0.98 # Set the threshold for considering a picture as "black" (in percent)
$pix = 0.15 # Set the threshold for considering a pixel "black" (in luminance)
### Main Program ______________________________________________________________________________________________________
foreach ($video in dir $folder -include $filter -exclude "*_???.*" -r){
### Set path to logfile
$logfile = "$($video.FullName)_ffmpeg.log"
### analyse each video with ffmpeg and search for black scenes
& $ffmpeg -i $video -vf blackdetect=d=`"$dur`":pic_th=`"$pic`":pix_th=`"$pix`" -an -f null - 2> $logfile
### Use regex to extract timings from logfile
$report = @()
Select-String 'black_start:.*black_end:' $logfile | % {
$black = "" | Select start, end, cut
# extract start time of black scene
$start_s = $_.line -match '(?<=black_start:)\S*(?= black_end:)' | % {$matches[0]}
$start_ts = [timespan]::fromseconds($start_s)
$black.start = "{0:HH:mm:ss.fff}" -f ([datetime]$start_ts.Ticks)
# extract duration of black scene
$end_s = $_.line -match '(?<=black_end:)\S*(?= black_duration:)' | % {$matches[0]}
$end_ts = [timespan]::fromseconds($end_s)
$black.end = "{0:HH:mm:ss.fff}" -f ([datetime]$end_ts.Ticks)
# calculate cut point: black start time + black duration / 2
$cut_s = ([double]$start_s + [double]$end_s) / 2
$cut_ts = [timespan]::fromseconds($cut_s)
$black.cut = "{0:HH:mm:ss.fff}" -f ([datetime]$cut_ts.Ticks)
$report += $black
}
### Write start time, duration and the cut point for each black scene to a seperate CSV
$report | Export-Csv -path "$($video.FullName)_cutpoints.csv" –NoTypeInformation
}
작동 원리
첫 번째 스크립트는 지정된 확장명과 일치하고 패턴과 일치하지 않는 모든 비디오 파일을 반복합니다. *_???.*
새 비디오 챕터의 이름이 지정 <filename>_###.<ext>
되었으므로 제외하려고합니다.
모든 검은 색 장면을 검색하고 시작 타임 스탬프 및 검은 색 장면 기간을 새 CSV 파일에 기록 <video_name>_cutpoints.txt
또한 다음과 같이 절단 점을 계산 cutpoint = black_start + black_duration / 2
합니다. 나중에이 타임 스탬프에서 비디오가 분할됩니다.
샘플 비디오 의 cutpoints.txt 파일은 다음과 같습니다.
start end cut
00:03:56.908 00:04:02.247 00:03:59.578
00:08:02.525 00:08:10.233 00:08:06.379
실행 후 원하는 경우 컷 포인트를 수동으로 조작 할 수 있습니다. 스크립트를 다시 실행하면 이전의 모든 내용이 덮어 쓰기됩니다. 작업을 수동으로 편집하고 다른 곳에 저장할 때는주의하십시오.
샘플 비디오의 경우 검은 장면을 감지하는 ffmpeg 명령은
$ffmpeg -i "Tape_10_3b.mp4" -vf blackdetect=d=4:pic_th=0.98:pix_th=0.15 -an -f null
스크립트의 옵션 섹션에서 편집 할 수있는 3 개의 중요한 숫자가 있습니다
d=4
4 초 이상의 검은 장면 만 감지됨을 의미
pic_th=0.98
사진을 "검은 색"(백분율)으로 간주하기위한 임계 값
pix=0.15
픽셀을 "검정"(휘도)으로 간주하기위한 임계 값을 설정합니다. 오래된 VHS 비디오가 있으므로 비디오에 완전히 검은 장면이 없습니다. 기본값 10이 작동하지 않고 임계 값을 약간 늘려야했습니다.
문제가 발생하면이라는 해당 로그 파일을 확인하십시오 <video_name>__ffmpeg.log
. 다음 줄이 없으면 검은 색 장면이 모두 감지 될 때까지 위에서 언급 한 숫자를 늘리십시오.
[blackdetect @ 0286ec80]
black_start:236.908 black_end:242.247 black_duration:5.33877
실행할 두 번째 스크립트 : cut_black.ps1
### Options __________________________________________________________________________________________________________
$ffmpeg = ".\ffmpeg.exe" # Set path to your ffmpeg.exe; Build Version: git-45581ed (2014-02-16)
$folder = ".\Videos\*" # Set path to your video folder; '\*' must be appended
$filter = @("*.mov","*.mp4") # Set which file extensions should be processed
### Main Program ______________________________________________________________________________________________________
foreach ($video in dir $folder -include $filter -exclude "*_???.*" -r){
### Set path to logfile
$logfile = "$($video.FullName)_ffmpeg.log"
### Read in all cutpoints from *_cutpoints.csv; concat to string e.g "00:03:23.014,00:06:32.289,..."
$cuts = ( Import-Csv "$($video.FullName)_cutpoints.csv" | % {$_.cut} ) -join ","
### put together the correct new name, "%03d" is a generic number placeholder for ffmpeg
$output = $video.directory.Fullname + "\" + $video.basename + "_%03d" + $video.extension
### use ffmpeg to split current video in parts according to their cut points
& $ffmpeg -i $video -f segment -segment_times $cuts -c copy -map 0 $output 2> $logfile
}
작동 원리
두 번째 스크립트는 첫 번째 스크립트와 동일한 방식으로 모든 비디오 파일을 반복합니다. 그것은 단지 읽 컷 대응에서 타임 스탬프 cutpoints.txt
비디오의.
다음으로, 챕터 파일에 적합한 파일 이름을 만들고 ffmpeg에게 비디오를 분할하도록 지시합니다. 현재 비디오는 다시 인코딩하지 않고 슬라이스됩니다 (초고속 및 무손실). 이로 인해 ffmpeg는 key_frames에서만 잘라낼 수 있으므로 컷 포인트 타임 스탬프와 함께 1-2 초의 부정확성이있을 수 있습니다. 우리는 단지 복사하고 다시 인코딩하지 않기 때문에 우리 자신의 key_frames를 삽입 할 수 없습니다.
샘플 비디오의 명령은
$ffmpeg -i "Tape_10_3b.mp4" -f segment -segment_times "00:03:59.578,00:08:06.379" -c copy -map 0 "Tape_10_3b_(%03d).mp4"
문제가 발생하면 해당 ffmpeg.log를 살펴보십시오.
참고 문헌
할 것
텍스트 형식보다 CSV 형식이 컷 포인트 파일보다 좋은지 OP에게 문의하면 Excel로 쉽게 편집 할 수 있습니다
»구현
타임 스탬프 형식을 초 단위가 아닌 [hh] : [mm] : [ss], [밀리 초]로 형식화하는 방법
구현»구현
각 장마다 mosaik png 파일을 작성하는 ffmpeg 명령
구현»구현
-c copy
OP의 시나리오에 충분한 지 또는 우리가 완전히 다시 인코딩해야 하는지를 설명 합니다.
Ryan이 이미있는 것 같습니다 .