Skip to content

Instantly share code, notes, and snippets.

@genegoykhman
Last active November 18, 2023 20:22
Show Gist options
  • Save genegoykhman/05f3d83acf72b79d86d93bace4e65c8e to your computer and use it in GitHub Desktop.
Save genegoykhman/05f3d83acf72b79d86d93bace4e65c8e to your computer and use it in GitHub Desktop.
#! /usr/bin/env ruby
# strip-silence version 1.1
#
# Usage:
# strip-silence input.mp4
#
# Description:
# Uses auto-editor to identify areas of silence in input.mp4,
# then uses ffmpeg to strip them out (without recompression).
# Creates a new file input_STRIPPED.mp4 in the same directory.
#
# Notes:
#
# 1. Cuts may not be exact because lossless cuts can only occur
# at keyframes.
#
# 2. Areas of silence shorter than 200 frames
# are ignored (this can be changed by editing the script).
#
# 3. Requires a working ruby, auto-editor, and ffmpeg installation.
#
# Copyright 2021 Gene Goykhman
#
# The MIT License
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of this software
# and associated documentation files (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge, publish, distribute,
# sublicense, and/or sell copies of the Software, and to permit persons to whom the Software
# is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or
# substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
require 'json'
def cleanup
Dir.glob('_segment*.*').each do |file|
File.delete(file)
end
end
def fps(input_file)
info = `ffmpeg -i \"#{input_file}\" 2>&1`
if /\s([\d\.]*)\sfps/ =~ info
return $1.to_f
end
return 0.0
end
def process_json(input_file, fps, json)
extension = File.extname(input_file)
segment_number = 1
File.open("_segments.txt", "w") do |f|
json["chunks"].each do |chunk|
if chunk[2] == 1
start_time = chunk[0] / fps
end_time = chunk[1] / fps
cmd = "ffmpeg -i \"#{input_file}\" -ss #{start_time} -to #{end_time} -c copy _segment#{segment_number}#{extension}"
`#{cmd}`
f.write("file _segment#{segment_number}#{extension}\n")
segment_number += 1
end
end
end
end
def combine_segments(input_file)
`ffmpeg -f concat -safe 0 -i _segments.txt -c copy \"#{File.basename(input_file, ".*")}_STRIPPED#{File.extname(input_file)}\"`
end
def process_file(input_file)
fps = fps(input_file)
abort("Unable to determine FPS of #{input_file}") unless fps > 0.0
`auto-editor \"#{input_file}\" --export json -mcut 200`
json_file = File.basename(input_file, ".*") + "_ALTERED.json"
json = JSON.parse(File.read(json_file))
process_json(input_file, fps, json)
File.delete(json_file)
combine_segments(input_file)
cleanup()
end
def iterate_files
ARGV.each do |input_file|
process_file(input_file)
end
end
cleanup()
iterate_files()
@AhmedThahir
Copy link

Is there a python version of this script?

@genegoykhman
Copy link
Author

@AhmedThahir No I don't think so.

@AhmedThahir
Copy link

I have rewritten the code in Python. Can you please help me out with it? I'm facing an issue.

WyattBlue/auto-editor#399

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment