Guest User

Untitled

a guest
Apr 20th, 2025
22
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.91 KB | None | 0 0
  1. #!/usr/bin/env python3
  2. import os, re, subprocess, time
  3. import urllib.request
  4.  
  5. # Add valid domains here
  6. VALID_DOMAINS = [
  7.     "files.catbox.moe",
  8. ]
  9.  
  10. # Add valid sound extensions here
  11. VALID_SOUNDEXTS = [
  12.     "mp3",
  13.     "wav",
  14.     "ogg",
  15.     "m4a",
  16. ]
  17.  
  18. # Wait this number of seconds between each file download, just so catbox doesn't whine because we're
  19. # downloading too much shit too fast. This might no be needed since calling ffmpeg to mix the final
  20. # file takes time on its own anyway so that already throttles our server calls
  21. THROTTLE = 0
  22.  
  23. # The mixed file's extension
  24. OUTPUT_EXTENSION = "mp4"
  25.  
  26. # You can specify the output codec here like  -c:v libvpx-vp9, you can also add things like -crf here or the audio codec
  27. # if it's empty, ffmpeg will choose default values for the output extension I think
  28. #OUTPUT_CODEC = "-c:v libvpx-vp9"    # For webm
  29. #OUTPUT_CODEC = "-c:v libx264"       # For mp4
  30. OUTPUT_CODEC = ""
  31.  
  32. # Don't mess with this
  33. VALID_FILENAME = r"(.+)\[sound=((?:https%3A%2F%2F)?(?:" + "|".join(VALID_DOMAINS) + ")%2F(.+\.(?:" + "|".join(VALID_SOUNDEXTS) + ")))\]\.(png|gif|jpeg|webm|mp4|jpg)"
  34.  
  35. def urldecode(text):
  36.     def subfunc(el):
  37.         return chr(int(el[0][1:], 16))
  38.     return re.sub("%[\da-fA-F]{2}", subfunc, text)
  39.  
  40. # Check if we can call a program with os.system()
  41. def program_exists(prog_name):
  42.     if os.name == 'nt': # for Windows
  43.         syscall = f"WHERE {prog_name}"
  44.         ret, err = subprocess.Popen(syscall, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
  45.     if os.name == 'posix':  # for Linux
  46.         syscall = f"which {prog_name}"
  47.         ret, err = subprocess.Popen(syscall, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
  48.     if err or not ret:
  49.         return False
  50.     return True
  51.  
  52. def download_soundfile(url, filename):
  53.     headers = {
  54.         'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.5756.197 Safari/537.36',
  55.         'Accept-Encoding': 'deflate',
  56.         'Accept-Language': 'en-US,en;q=0.5',
  57.         'Cache-Control' : 'no-cache',
  58.     }
  59.     req = urllib.request.Request(url, headers=headers)
  60.     data = urllib.request.urlopen(req)
  61.     with open(filename,'wb') as output:
  62.         output.write(data.read())
  63.  
  64. def system_call(cmd):
  65.     if os.name == 'nt': # for Windows
  66.         ret, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
  67.     if os.name == 'posix':  # for Linux
  68.         ret, err = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
  69.     return ret, err
  70.  
  71. def get_song_length(fname):
  72.     cmd = f'ffprobe -hide_banner "{fname}"'
  73.     # For some reason ffprobe returns data in err
  74.     ret, err = system_call(cmd)
  75.     res = re.findall("Duration: (\d+:\d{2}:\d{2}(?:\.\d+))", err.decode('utf-8'))
  76.     if not res:
  77.         return None
  78.     tmp = res[0].split(":")
  79.     hours, minutes, seconds = int(tmp[0]), int(tmp[1]), float(tmp[2])
  80.     return (hours * 3600) + (minutes * 60) + seconds
  81.  
  82. # Check if we have ffmpeg
  83. if not program_exists("ffmpeg"):
  84.     print("ffmpeg couldn't be found")
  85.     exit()
  86.  
  87. for file in os.listdir():
  88.     res = re.match(VALID_FILENAME, file)
  89.     if not res:
  90.         continue
  91.  
  92.     imgname, soundurl, soundfname, ext = res[1], urldecode(res[2]), res[3], res[4]
  93.     if not soundurl.startswith("https://"):
  94.         soundurl = "https://" + soundurl
  95.  
  96.     if not os.path.exists(soundfname):
  97.         print(f"File {soundfname} does not exist, downloading")
  98.         download_soundfile(soundurl, soundfname)
  99.         if THROTTLE > 0:
  100.             print(f"Waiting {THROTTLE} seconds")
  101.             time.sleep(THROTTLE)
  102.  
  103.     song_length = get_song_length(soundfname)
  104.     video_length = 0
  105.     if(ext in ['mp4', 'webm']):
  106.         video_length = get_song_length(file)
  107.  
  108.     # Because we have to use a different ffmpeg command depending on each case
  109.     if(ext in ['jpg', 'png', 'jpeg']):
  110.         # Simple case a static image and an mp3
  111.         ffmpeg_cmd = f'ffmpeg -hide_banner -loop 1 -i "{file}" -i "{soundfname}" -t {song_length} {OUTPUT_CODEC} -vf "fps=25,format=yuv420p" "out-{imgname}.{OUTPUT_EXTENSION}"'
  112.     elif ext == 'gif':
  113.         # Gif and mp3
  114.         ffmpeg_cmd = f'ffmpeg -ignore_loop 0 -i "{file}" -i "{soundfname}" -t {song_length} {OUTPUT_CODEC} -vf "fps=25,format=yuv420p" "out-{imgname}.{OUTPUT_EXTENSION}"'
  115.     elif song_length > video_length:
  116.         # Song is longer than video so we will loop video
  117.         ffmpeg_cmd = f'ffmpeg -hide_banner -stream_loop -1 -i "{file}" -i "{soundfname}" -t {song_length} {OUTPUT_CODEC} -vf "fps=25,format=yuv420p" "out-{imgname}.{OUTPUT_EXTENSION}"'
  118.     else:
  119.         # Else song has the same length as video, presumably
  120.         ffmpeg_cmd = f'ffmpeg -hide_banner -i "{file}" -i "{soundfname}" {OUTPUT_CODEC}  "out-{imgname}.{OUTPUT_EXTENSION}"'
  121.  
  122.     os.system(ffmpeg_cmd)
  123.  
  124. print("\n\nPress enter to exit")
  125. input()
Add Comment
Please, Sign In to add comment