Guest User

Untitled

a guest
Jul 25th, 2025
61
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.79 KB | None | 0 0
  1. import datetime
  2. import getopt
  3. import logging
  4. import os
  5. import shutil
  6. import subprocess
  7. import sys
  8. import time
  9.  
  10. import config
  11.  
  12.  
  13. class KickRecorder:
  14. def __init__(self):
  15. self.ffmpeg_path = "ffmpeg"
  16. self.disable_ffmpeg = False
  17. self.refresh = 15
  18. self.root_path = config.root_path
  19. self.username = config.username
  20. self.quality = "best"
  21.  
  22. def run(self):
  23. recorded_path = os.path.join(self.root_path, "recorded", self.username)
  24. processed_path = os.path.join(self.root_path, "processed", self.username)
  25.  
  26. os.makedirs(recorded_path, exist_ok=True)
  27. os.makedirs(processed_path, exist_ok=True)
  28.  
  29. if self.refresh < 15:
  30. logging.warning("Check interval should not be lower than 15 seconds.")
  31. self.refresh = 15
  32.  
  33. # Fix any previously recorded files
  34. for f in os.listdir(recorded_path):
  35. full_path = os.path.join(recorded_path, f)
  36. if os.path.isfile(full_path):
  37. self.process_recorded_file(full_path, os.path.join(processed_path, f))
  38.  
  39. logging.info("Checking Kick stream for %s every %s seconds", self.username, self.refresh)
  40. self.loop_check(recorded_path, processed_path)
  41.  
  42. def is_kick_stream_live(self):
  43. try:
  44. result = subprocess.run(
  45. ["streamlink", f"https://kick.com/{self.username}"],
  46. capture_output=True,
  47. text=True,
  48. timeout=10
  49. )
  50. return "Available streams:" in result.stdout
  51. except Exception as e:
  52. logging.error("Error checking stream status: %s", e)
  53. return False
  54.  
  55. def loop_check(self, recorded_path, processed_path):
  56. while True:
  57. if self.is_kick_stream_live():
  58. logging.info("%s is live. Starting recording.", self.username)
  59. filename = f"{self.username} - {datetime.datetime.now().strftime('%Y-%m-%d %Hh%Mm%Ss')}.mp4"
  60. filename = "".join(x for x in filename if x.isalnum() or x in [" ", "-", "_", "."])
  61. recorded_filename = os.path.join(recorded_path, filename)
  62. processed_filename = os.path.join(processed_path, filename)
  63.  
  64. subprocess.call([
  65. "streamlink", f"https://kick.com/{self.username}", self.quality,
  66. "-o", recorded_filename
  67. ])
  68.  
  69. if os.path.exists(recorded_filename):
  70. self.process_recorded_file(recorded_filename, processed_filename)
  71. else:
  72. logging.warning("Recording file not found after recording session.")
  73. else:
  74. logging.info("%s is offline. Checking again in %s seconds.", self.username, self.refresh)
  75. time.sleep(self.refresh)
  76.  
  77. def process_recorded_file(self, recorded_filename, processed_filename):
  78. if self.disable_ffmpeg:
  79. logging.info("Moving %s to processed directory", recorded_filename)
  80. shutil.move(recorded_filename, processed_filename)
  81. else:
  82. logging.info("Fixing and processing %s", recorded_filename)
  83. self.ffmpeg_copy_and_fix_errors(recorded_filename, processed_filename)
  84.  
  85. def ffmpeg_copy_and_fix_errors(self, recorded_filename, processed_filename):
  86. try:
  87. subprocess.call([
  88. self.ffmpeg_path, "-err_detect", "ignore_err", "-i", recorded_filename, "-c", "copy",
  89. processed_filename
  90. ])
  91. os.remove(recorded_filename)
  92. except Exception as e:
  93. logging.error("FFmpeg error: %s", e)
  94.  
  95.  
  96. def main(argv):
  97. kick_recorder = KickRecorder()
  98. usage = "kick-recorder.py -u <username> -q <quality>"
  99.  
  100. logging.basicConfig(filename="kick-recorder.log", level=logging.INFO)
  101. logging.getLogger().addHandler(logging.StreamHandler())
  102.  
  103. try:
  104. opts, _ = getopt.getopt(argv, "hu:q:l:", ["username=", "quality=", "log=", "logging=", "disable-ffmpeg"])
  105. except getopt.GetoptError:
  106. print(usage)
  107. sys.exit(2)
  108.  
  109. for opt, arg in opts:
  110. if opt == "-h":
  111. print(usage)
  112. sys.exit()
  113. elif opt in ("-u", "--username"):
  114. kick_recorder.username = arg
  115. elif opt in ("-q", "--quality"):
  116. kick_recorder.quality = arg
  117. elif opt in ("-l", "--log", "--logging"):
  118. level = getattr(logging, arg.upper(), None)
  119. if not isinstance(level, int):
  120. raise ValueError(f"Invalid log level: {arg}")
  121. logging.basicConfig(level=level)
  122. elif opt == "--disable-ffmpeg":
  123. kick_recorder.disable_ffmpeg = True
  124.  
  125. kick_recorder.run()
  126.  
  127.  
  128. if __name__ == "__main__":
  129. main(sys.argv[1:])
  130.  
Advertisement
Add Comment
Please, Sign In to add comment