Skip to content

Instantly share code, notes, and snippets.

@d33tah
Created February 11, 2023 08:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d33tah/68d58fd41ca5fb8282162681fb1100ff to your computer and use it in GitHub Desktop.
Save d33tah/68d58fd41ca5fb8282162681fb1100ff to your computer and use it in GitHub Desktop.
Generates a collage based on a set of videos
video_files_by_sha1
output
*.pyc

HSŁ collage generator - build instructions

  1. Download this gist as a git repository
  2. Pull a .zip file with all contents of this directory: https://drive.google.com/drive/folders/1cJVElo-6QvkmIRygEhOTOfhQd87Ocmnz?usp=sharing
  3. Unzip the directory so that the git checkout contains video_files_by_sha1 directory that has .mp4 files directly in it
  4. Run sudo docker-compose up --build, wait about a minute
  5. The output you're looking for is in output/collage.mp4.
version: '3.0'
services:
collage:
build: .
volumes:
- ./video_files_by_sha1:/video_files_by_sha1
- ./output:/output
FROM python:3.11
RUN apt-get update && apt-get install -y ffmpeg && rm -rf /var/lib/apt/lists/* /var/cache/apt/*
ADD ./main.py .
CMD ["python", "main.py"]
#!/usr/bin/env python3
import subprocess
import pathlib
def ffmpeg_collage(fname1, fname2, fname3, fname4, outfname, length_sec=1):
subprocess.call(
[
"ffmpeg",
"-i",
fname1,
"-i",
fname2,
"-i",
fname3,
"-i",
fname4,
"-filter_complex",
"nullsrc=size=640x480 [base];"
" [0:v] setpts=PTS-STARTPTS, scale=320x240 [upperleft];"
" [1:v] setpts=PTS-STARTPTS, scale=320x240 [upperright];"
" [2:v] setpts=PTS-STARTPTS, scale=320x240 [lowerleft];"
" [3:v] setpts=PTS-STARTPTS, scale=320x240 [lowerright];"
" [base][upperleft] overlay=shortest=1 [tmp1];"
" [tmp1][upperright] overlay=shortest=1:x=320 [tmp2];"
" [tmp2][lowerleft] overlay=shortest=1:y=240 [tmp3];"
" [tmp3][lowerright] overlay=shortest=1:x=320:y=240",
"-t",
str(length_sec),
"-c:v",
"libx264",
outfname,
]
)
def write_list_of_files():
list_of_files = list(pathlib.Path("/output").glob("*.mp4"))
with open("/output/files.txt", "w") as f:
for fh in list_of_files:
f.write(f"file '{fh.name}'\n")
def concatenate_files():
subprocess.call(
[
"ffmpeg",
"-f",
"concat",
"-safe",
"0",
"-i",
"/output/files.txt",
"-c",
"copy",
"/output/collage.mp4",
]
)
def create_chunks_of_four():
list_of_files = list(pathlib.Path("/video_files_by_sha1").glob("*.mp4"))
chunks_of_four = [
list_of_files[i : i + 4] for i in range(0, len(list_of_files), 4)
]
for chunk in chunks_of_four:
if len(chunk) < 4:
continue
ffmpeg_collage(
chunk[0],
chunk[1],
chunk[2],
chunk[3],
"/output/" + "".join([f.name for f in chunk]) + ".mp4",
)
def main():
create_chunks_of_four()
write_list_of_files()
concatenate_files()
if __name__ == "__main__":
main()
[tool.black]
line-length = 79
target-version = ['py37']
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment