aboutsummaryrefslogtreecommitdiffstats
path: root/cogs/music/media_processing.py
diff options
context:
space:
mode:
authorsalmonik <raisersoft@proton.me>2026-02-04 16:16:26 +0100
committersalmonik <raisersoft@proton.me>2026-02-04 16:16:26 +0100
commitce61bf6bd5949046d15f58609f572fedcb8a073e (patch)
treecafaa12f11a06337bda5de08881e395ac66c1c11 /cogs/music/media_processing.py
parentbetter reply context (diff)
downloadsenator-sperma-ce61bf6bd5949046d15f58609f572fedcb8a073e.tar.gz
senator-sperma-ce61bf6bd5949046d15f58609f572fedcb8a073e.zip
refactor music
Diffstat (limited to '')
-rw-r--r--cogs/music/media_processing.py124
1 files changed, 124 insertions, 0 deletions
diff --git a/cogs/music/media_processing.py b/cogs/music/media_processing.py
new file mode 100644
index 0000000..430b51f
--- /dev/null
+++ b/cogs/music/media_processing.py
@@ -0,0 +1,124 @@
1# This file is part of Senator Sperma
2# Licensed under the GPL-3.0 License
3# Copyright (C) 2026 Salmonik @ salmonik@tuta.io
4# https://codeberg.org/salmonik/senator-sperma
5
6import os
7import asyncio
8import logging
9from pathlib import Path
10
11import yt_dlp
12from youtubesearchpython import VideosSearch
13
14logger = logging.getLogger(__name__)
15
16class MediaDownloader:
17 """Handles downloading media from various sources."""
18
19 @staticmethod
20 async def download(ctx, url):
21 """Download audio from YouTube URL."""
22 # Create temp directory if it doesn't exist
23 temp_dir = os.path.join('cogs', 'temp', 'music')
24 os.makedirs(temp_dir, exist_ok=True)
25
26 ytdl_opts = {
27 "outtmpl": os.path.join(temp_dir, "%(title)s.%(ext)s"),
28 "postprocessors": [
29 {
30 "key": "FFmpegExtractAudio",
31 "preferredcodec": "mp3",
32 "preferredquality": "192",
33 }
34 ],
35 "force_ipv4": True,
36 }
37
38 try:
39 with yt_dlp.YoutubeDL(ytdl_opts) as ydl:
40 info_dict = ydl.extract_info(url, download=True)
41 # Get the base filename without extension
42 base_filename = os.path.splitext(ydl.prepare_filename(info_dict))[0]
43 # Add .mp3 extension since we're extracting audio
44 filename = f"{base_filename}.mp3"
45 logger.info(f"Downloaded file: {filename}")
46 return filename
47 except Exception as e:
48 logger.error(f"Error downloading video: {e}")
49 await ctx.respond("eror pobirajync wideło", ephemeral=True)
50
51 @staticmethod
52 async def get_url(ctx, query):
53 """Search YouTube and get URL for a query."""
54 search = VideosSearch(query, limit=1)
55 if search.result()["result"]:
56 title = search.result()["result"][0]["title"]
57 url = search.result()["result"][0]["link"]
58 logger.info(f"Found video: {title}")
59 return url, title
60 else:
61 logger.warning("No results found for the query.")
62 await ctx.respond("nic ni ma", ephemeral=True)
63 return None
64
65class AudioCompressor:
66 """Handles audio compression using FFmpeg."""
67
68 @staticmethod
69 async def compress(ctx, filename):
70 """Compress audio file to opus format."""
71 if not filename:
72 await ctx.respond("dzie wideło", ephemeral=True)
73 return None
74
75 # Create temp directory if it doesn't exist
76 temp_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'temp', 'compressed')
77 os.makedirs(temp_dir, exist_ok=True)
78
79 # Create a temporary output filename in the temp directory
80 base_name = os.path.basename(filename)
81 output_filename = os.path.join(temp_dir, f"{os.path.splitext(base_name)[0]}_compressed.opus")
82
83 # Ensure the output directory exists
84 os.makedirs(os.path.dirname(output_filename) or '.', exist_ok=True)
85
86 # Use proper quoting for filenames with spaces
87 ffmpeg_command = [
88 'ffmpeg',
89 '-y', # Overwrite output file if it exists
90 '-i', filename,
91 '-ac', '1', # Mono audio
92 '-b:a', '500', # 500k bitrate
93 '-acodec', 'libopus',
94 output_filename
95 ]
96
97 try:
98 logger.info(f"Running FFmpeg command: {' '.join(ffmpeg_command)}")
99 process = await asyncio.create_subprocess_exec(
100 *ffmpeg_command,
101 stdout=asyncio.subprocess.PIPE,
102 stderr=asyncio.subprocess.PIPE
103 )
104
105 _, stderr = await process.communicate()
106
107 if process.returncode != 0:
108 error_msg = stderr.decode()
109 logger.error(f"FFmpeg error ({process.returncode}): {error_msg}")
110 await ctx.respond("eror kompresujync pilk", ephemeral=True)
111 return None
112
113 if not os.path.exists(output_filename):
114 logger.error(f"Output file was not created: {output_filename}")
115 await ctx.respond("eror kompresujync pilk - output file not created", ephemeral=True)
116 return None
117
118 logger.info(f"Successfully compressed file: {output_filename}")
119 return output_filename
120
121 except Exception as e:
122 logger.error(f"Error compressing file: {str(e)}", exc_info=True)
123 await ctx.respond(f"eror kompresujync pilk: {str(e)}", ephemeral=True)
124 return None