mirror of
https://github.com/vondas-network/videobeaux.git
synced 2025-12-19 22:30:07 +01:00
initial commit
This commit is contained in:
0
programs/__init__.py
Normal file
0
programs/__init__.py
Normal file
10
programs/convert.py
Normal file
10
programs/convert.py
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
from utils.ffmpeg_operations import run_ffmpeg_command
|
||||||
|
|
||||||
|
def convert_video(input_file, output_file, format):
|
||||||
|
command = [
|
||||||
|
"ffmpeg",
|
||||||
|
"-i", input_file,
|
||||||
|
output_file
|
||||||
|
]
|
||||||
|
run_ffmpeg_command(command)
|
||||||
|
print(f"Video converted to {format} format and saved as {output_file}")
|
||||||
11
programs/extract_frames.py
Normal file
11
programs/extract_frames.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
from utils.ffmpeg_operations import run_ffmpeg_command
|
||||||
|
|
||||||
|
def extract_frames(input_file, output_folder, frame_rate):
|
||||||
|
command = [
|
||||||
|
"ffmpeg",
|
||||||
|
"-i", input_file,
|
||||||
|
"-vf", f"fps={frame_rate}",
|
||||||
|
f"{output_folder}/frame_%04d.png"
|
||||||
|
]
|
||||||
|
run_ffmpeg_command(command)
|
||||||
|
print(f"Frames extracted from {input_file} at {frame_rate} fps and saved to {output_folder}")
|
||||||
12
programs/resize.py
Normal file
12
programs/resize.py
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
from utils.ffmpeg_operations import run_ffmpeg_command
|
||||||
|
|
||||||
|
def resize_video(input_file, output_file, width, height):
|
||||||
|
command = [
|
||||||
|
"ffmpeg",
|
||||||
|
"-i", input_file,
|
||||||
|
"-vf", f"scale={width}:{height}",
|
||||||
|
output_file
|
||||||
|
]
|
||||||
|
|
||||||
|
run_ffmpeg_command(command)
|
||||||
|
print(f"Video resized to {width}x{height} and saved as {output_file}")
|
||||||
39
programs/silence_extraction.py
Normal file
39
programs/silence_extraction.py
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
import sys
|
||||||
|
from videogrep import parse_transcript, create_supercut
|
||||||
|
|
||||||
|
|
||||||
|
def slncx_main(min_d, max_d, adj, input_file, output_file):
|
||||||
|
print('DID WE MAKE IT^&(#(*&#(*&#(*&W#(*#&(*#&(*#&(*#&#*(&#))')
|
||||||
|
print(input_file)
|
||||||
|
# the min and max duration of silences to extract
|
||||||
|
min_duration = min_d #0.1
|
||||||
|
max_duration = max_d #1000.0
|
||||||
|
|
||||||
|
# value to to trim off the end of each clip
|
||||||
|
adjuster = adj #0.0
|
||||||
|
|
||||||
|
filenames = input_file
|
||||||
|
|
||||||
|
silences = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
for filename in filenames:
|
||||||
|
timestamps = parse_transcript(filename)
|
||||||
|
|
||||||
|
words = []
|
||||||
|
print(timestamps)
|
||||||
|
for sentence in timestamps:
|
||||||
|
words += sentence['words']
|
||||||
|
|
||||||
|
for word1, word2 in zip(words[:-2], words[1:]):
|
||||||
|
start = word1['end']
|
||||||
|
end = word2['start'] - adjuster
|
||||||
|
duration = end - start
|
||||||
|
if duration > min_duration and duration < max_duration:
|
||||||
|
silences.append({'start': start, 'end': end, 'file': filename})
|
||||||
|
|
||||||
|
create_supercut(silences, f"{output_file}.mp4")
|
||||||
|
return "ok"
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
return e
|
||||||
57
requirements.txt
Normal file
57
requirements.txt
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
annotated-types==0.6.0
|
||||||
|
beautifulsoup4==4.12.3
|
||||||
|
blis==0.7.11
|
||||||
|
Brotli==1.1.0
|
||||||
|
catalogue==2.0.10
|
||||||
|
certifi==2024.2.2
|
||||||
|
cffi==1.16.0
|
||||||
|
charset-normalizer==3.3.2
|
||||||
|
click==8.1.7
|
||||||
|
cloudpathlib==0.16.0
|
||||||
|
colorama==0.4.6
|
||||||
|
confection==0.1.4
|
||||||
|
cupy-cuda11x==12.3.0
|
||||||
|
cymem==2.0.8
|
||||||
|
decorator==4.4.2
|
||||||
|
en-core-web-sm @ https://github.com/explosion/spacy-models/releases/download/en_core_web_sm-3.7.1/en_core_web_sm-3.7.1-py3-none-any.whl#sha256=86cc141f63942d4b2c5fcee06630fd6f904788d2f0ab005cce45aadb8fb73889
|
||||||
|
fastrlock==0.8.2
|
||||||
|
idna==3.7
|
||||||
|
imageio==2.34.1
|
||||||
|
imageio-ffmpeg==0.4.9
|
||||||
|
Jinja2==3.1.4
|
||||||
|
langcodes==3.4.0
|
||||||
|
language_data==1.2.0
|
||||||
|
marisa-trie==1.1.1
|
||||||
|
MarkupSafe==2.1.5
|
||||||
|
moviepy==1.0.3
|
||||||
|
murmurhash==1.0.10
|
||||||
|
mutagen==1.47.0
|
||||||
|
numpy==1.26.4
|
||||||
|
packaging==24.0
|
||||||
|
pillow==10.3.0
|
||||||
|
preshed==3.0.9
|
||||||
|
proglog==0.1.10
|
||||||
|
pycparser==2.22
|
||||||
|
pycryptodomex==3.20.0
|
||||||
|
pydantic==2.7.1
|
||||||
|
pydantic_core==2.18.2
|
||||||
|
pydub==0.25.1
|
||||||
|
requests==2.31.0
|
||||||
|
smart-open==6.4.0
|
||||||
|
soupsieve==2.5
|
||||||
|
spacy==3.7.4
|
||||||
|
spacy-legacy==3.0.12
|
||||||
|
spacy-loggers==1.0.5
|
||||||
|
srsly==2.4.8
|
||||||
|
srt==3.5.3
|
||||||
|
thinc==8.2.3
|
||||||
|
tqdm==4.66.4
|
||||||
|
typer==0.9.4
|
||||||
|
typing_extensions==4.11.0
|
||||||
|
urllib3==2.2.1
|
||||||
|
videogrep==2.3.0
|
||||||
|
vosk==0.3.45
|
||||||
|
wasabi==1.1.2
|
||||||
|
weasel==0.3.4
|
||||||
|
websockets==12.0
|
||||||
|
yt-dlp==2024.4.9
|
||||||
0
utils/__init__.py
Normal file
0
utils/__init__.py
Normal file
7
utils/ffmpeg_operations.py
Normal file
7
utils/ffmpeg_operations.py
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import subprocess
|
||||||
|
|
||||||
|
def run_ffmpeg_command(command):
|
||||||
|
try:
|
||||||
|
subprocess.run(command, check=True)
|
||||||
|
except subprocess.CalledProcessError as e:
|
||||||
|
print(f"An error occurred: {e}")
|
||||||
133
videobeaux.py
Normal file
133
videobeaux.py
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import typer
|
||||||
|
import yaml
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from programs import silence_extraction, resize, convert, extract_frames
|
||||||
|
|
||||||
|
config_file = Path(__file__).parent / "config.yaml"
|
||||||
|
|
||||||
|
def load_config():
|
||||||
|
with open(config_file, 'r') as file:
|
||||||
|
return yaml.safe_load(file)
|
||||||
|
|
||||||
|
config = load_config()
|
||||||
|
|
||||||
|
app = typer.Typer()
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def silence_xtraction(
|
||||||
|
min_d: int = typer.Option(None, help="Width of the output video"),
|
||||||
|
max_d: int = typer.Option(None, help="Height of the output video"),
|
||||||
|
adj: int = typer.Option(None, help="Height of the output video"),
|
||||||
|
input_file: str = typer.Option(None, help="Input video file"),
|
||||||
|
output_file: str = typer.Option(None, help="Output video file")
|
||||||
|
):
|
||||||
|
params = {
|
||||||
|
"min_d": min_d,
|
||||||
|
"max_d": max_d,
|
||||||
|
"adj": adj,
|
||||||
|
"input_file": input_file,
|
||||||
|
"output_file": output_file,
|
||||||
|
|
||||||
|
}
|
||||||
|
defaults = config['silence_x']
|
||||||
|
params = {key: params.get(key) or defaults[key] for key in defaults}
|
||||||
|
|
||||||
|
silence_extraction.slncx_main(**params)
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def resize_video(
|
||||||
|
input_file: str = typer.Option(None, help="Input video file"),
|
||||||
|
output_file: str = typer.Option(None, help="Output video file"),
|
||||||
|
width: int = typer.Option(None, help="Width of the output video"),
|
||||||
|
height: int = typer.Option(None, help="Height of the output video")
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Resize a video to the given width and height.
|
||||||
|
"""
|
||||||
|
params = {
|
||||||
|
"input_file": input_file,
|
||||||
|
"output_file": output_file,
|
||||||
|
"width": width,
|
||||||
|
"height": height
|
||||||
|
}
|
||||||
|
defaults = config['resize']
|
||||||
|
params = {key: params.get(key) or defaults[key] for key in defaults}
|
||||||
|
|
||||||
|
resize.resize_video(**params)
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def convert_video(
|
||||||
|
input_file: str = typer.Option(None, help="Input video file"),
|
||||||
|
output_file: str = typer.Option(None, help="Output video file"),
|
||||||
|
format: str = typer.Option(None, help="Format of the output video")
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Convert a video to a different format.
|
||||||
|
"""
|
||||||
|
if not input_file:
|
||||||
|
input_file = config['convert']['input_file']
|
||||||
|
if not output_file:
|
||||||
|
output_file = config['convert']['output_file']
|
||||||
|
if not format:
|
||||||
|
format = config['convert']['format']
|
||||||
|
|
||||||
|
convert.convert_video(input_file, output_file, format)
|
||||||
|
|
||||||
|
@app.command()
|
||||||
|
def extract_frames(
|
||||||
|
input_file: str = typer.Option(None, help="Input video file"),
|
||||||
|
output_folder: str = typer.Option(None, help="Output folder for frames"),
|
||||||
|
frame_rate: int = typer.Option(None, help="Frame rate for extracting frames")
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Extract frames from a video at the specified frame rate.
|
||||||
|
"""
|
||||||
|
if not input_file:
|
||||||
|
input_file = config['extract_frames']['input_file']
|
||||||
|
if not output_folder:
|
||||||
|
output_folder = config['extract_frames']['output_folder']
|
||||||
|
if not frame_rate:
|
||||||
|
frame_rate = config['extract_frames']['frame_rate']
|
||||||
|
|
||||||
|
extract_frames.extract_frames(input_file, output_folder, frame_rate)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
app()
|
||||||
|
|
||||||
|
|
||||||
|
'''def main():
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="VideoBeaux - It's You're Best Friend")
|
||||||
|
subparsers = parser.add_subparsers(title='Subcommands', dest='command', help='Sub-command help')
|
||||||
|
|
||||||
|
|
||||||
|
# Program selection
|
||||||
|
#add_parser = subparsers.add_parser('program', help='Add a new task')
|
||||||
|
#add_parser.add_argument('task', type=str, help='The task to add')
|
||||||
|
|
||||||
|
# Project Management
|
||||||
|
#prjmgmt_parser = subparsers.add_parser('project', help='Add a new task')
|
||||||
|
#prjmgmt_parser.add_argument('--input_file', dest='infile', type=str, help='Full path to input file') # todo - use a path defined in config
|
||||||
|
#prjmgmt_parser.add_argument('--output_file', dest='outfile', type=str, help='filename of output file that will be save in videobeaux root dir') # todo - use a path defined in config
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# Silence Xtraction
|
||||||
|
silencextraction_parser = subparsers.add_parser('silence-xtraction', help='extracts silence from a given video')
|
||||||
|
silencextraction_parser.add_argument('--min_d', dest='mind', type=int, help='Minimum duration of a silent chunk')
|
||||||
|
silencextraction_parser.add_argument('--max_d', dest='maxd', type=int, help='Maximum duration of a silent chunk')
|
||||||
|
silencextraction_parser.add_argument('--adj', dest='adj', type=int, help='Maximum duration of a silent chunk')
|
||||||
|
silencextraction_parser.add_argument('--input_file', dest='infile', type=str, help='Full path to input file') # todo - use a path defined in config
|
||||||
|
silencextraction_parser.add_argument('--output_file', dest='outfile', type=str, help='filename of output file that will be save in videobeaux root dir') # todo - use a path defined in config
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if args.command == 'silence-xtraction':
|
||||||
|
silence_extraction.slncx_main(args.mind, args.maxd, args.adj, args.infile, args.outfile)
|
||||||
|
|
||||||
|
else:
|
||||||
|
parser.print_help()
|
||||||
|
|
||||||
|
'''
|
||||||
Reference in New Issue
Block a user