Rya*_*yan 12 video ffmpeg video-editing
我有 65 个名为 tape_01.mov、tape_02.mov、...、tape_65.mov 的 .mov 视频文件。每个大约 2.5 小时,占用许多 GB 空间。它们是 VHS 磁带(我家的“家庭电影”)的数字副本。
每个 2.5 小时的 .mov 视频文件都包含许多“章节”(从某种意义上说,有时场景以淡入黑屏结束,然后新场景淡入)。
我的主要目标是将 65 个大文件按章节切成小文件。我希望通过检测“场景”之间的黑框来自动完成。
我可以使用 ffmpeg(或任何东西)来传递 65 个原始文件名并让它自动迭代每个视频并将其切碎,命名生成的片段tape_01-ch_01.mov、tape_01-ch_02.mov、tape_01-ch_03.mov,等等?而且我希望它无需重新编码即可完成(我希望它是一个简单的无损切片)。
我怎样才能做到这一点?
以下是我想要的步骤:
我希望这些脚本是可以在 Mac、Ubuntu 和 Windows Git Bash 中运行的 shell 脚本。
nix*_*xda 12
这里有两个 PowerShell 脚本,用于将长视频按黑色场景拆分成更小的章节。
将它们另存为 Detect_black.ps1 和 Cut_black.ps1。下载适用于 Windows 的 ffmpeg并在选项部分下告诉脚本您的 ffmpeg.exe 和视频文件夹的路径。

这两个脚本都不会触及现有的视频文件,它们保持不变。
但是,您将在输入视频所在的同一位置获得几个新文件

### 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
}
Run Code Online (Sandbox Code Playgroud)
第一个脚本遍历所有匹配指定扩展名但不匹配 pattern 的视频文件*_???.*,因为新的视频章节被命名<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
Run Code Online (Sandbox Code Playgroud)
运行后,您可以根据需要手动操作切割点。如果您再次运行该脚本,所有旧内容都会被覆盖。手动编辑并将您的工作保存在其他地方时要小心。
对于示例视频,检测黑色场景的 ffmpeg 命令是
$ffmpeg -i "Tape_10_3b.mp4" -vf blackdetect=d=4:pic_th=0.98:pix_th=0.15 -an -f null
Run Code Online (Sandbox Code Playgroud)
在脚本的选项部分有 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
Run Code Online (Sandbox Code Playgroud)
### 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
}
Run Code Online (Sandbox Code Playgroud)
第二个脚本以与第一个脚本相同的方式遍历所有视频文件。它仅从相应的视频中读取剪切时间戳cutpoints.txt。
接下来,它为章节文件组合一个合适的文件名,并告诉 ffmpeg 对视频进行分段。目前,视频切片无需重新编码(超快和无损)。因此,切割点时间戳可能存在 1-2 秒的不准确,因为 ffmpeg 只能在关键帧处进行切割。由于我们只是复制而不重新编码,因此我们无法自行插入 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"
Run Code Online (Sandbox Code Playgroud)
如果出现问题,请查看相应的ffmpeg.log
-c copy对于 OP 的场景是否足够,或者我们需要完全重新编码。tbe*_*nz9 -2
我希望我是错的,但我认为你的要求是不可能的。重新编码视频时可能有可能,但作为“简单的无损切片”我不知道有什么方法。
许多视频编辑程序都具有自动分析功能或类似功能,可以在黑帧上分割视频,但这需要对视频进行重新编码。
祝你好运!
| 归档时间: |
|
| 查看次数: |
10170 次 |
| 最近记录: |