Skip to content

Instantly share code, notes, and snippets.

@abrorbekuz
Created November 15, 2024 20:24
Show Gist options
  • Save abrorbekuz/76e434335b4bf20448a1a583cf91d8fb to your computer and use it in GitHub Desktop.
Save abrorbekuz/76e434335b4bf20448a1a583cf91d8fb to your computer and use it in GitHub Desktop.
wo&man
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
import os
from pydub import AudioSegment
import librosa
import soundfile as sf
import tempfile
import time
API_TOKEN = "<TOKEN>"
bot = telebot.TeleBot(API_TOKEN)
TEMP_DIR = "temp_audio"
os.makedirs(TEMP_DIR, exist_ok=True)
def process_audio(file_path, pitch_steps, progress_message):
progress_message("Processing: Converting to WAV...", 10)
audio = AudioSegment.from_file(file_path)
wav_file = os.path.join(TEMP_DIR, "temp_audio.wav")
audio.export(wav_file, format="wav")
progress_message("WAV Conversion Complete!", 20)
audio_data, sample_rate = librosa.load(wav_file)
progress_message("Processing: Shifting pitch...", 50)
shifted_audio = librosa.effects.pitch_shift(audio_data, sr=sample_rate, n_steps=pitch_steps)
progress_message("Pitch Shift Complete!", 70)
shifted_wav = os.path.join(TEMP_DIR, "shifted_audio.wav")
sf.write(shifted_wav, shifted_audio, sample_rate)
progress_message("Processing: Converting back to MP3...", 90)
processed_file = os.path.join(TEMP_DIR, "processed_audio.mp3")
output_audio = AudioSegment.from_wav(shifted_wav)
output_audio.export(processed_file, format="mp3")
os.remove(wav_file)
os.remove(shifted_wav)
progress_message("Processing complete!", 100)
return processed_file
@bot.message_handler(commands=["start"])
def start_message(message):
bot.reply_to(message, "Hi! Upload an audio file, and then select pitch adjustment:\n"
"1. Choose Masculine or Feminine.\n"
"2. Select a zoom range.\n"
"3. Pick the exact pitch value.")
@bot.message_handler(content_types=["audio", "voice", "document"])
def handle_audio(message):
file_info = bot.get_file(message.audio.file_id if message.content_type == "audio" else message.document.file_id)
downloaded_file = bot.download_file(file_info.file_path)
file_path = os.path.join(TEMP_DIR, f"{message.id}_input_audio")
with open(file_path, "wb") as f:
f.write(downloaded_file)
bot.reply_to(message, "Audio received! Now select Masculine or Feminine:",
reply_markup=create_gender_keyboard(message.message_id))
def create_gender_keyboard(message_id):
markup = InlineKeyboardMarkup()
markup.row(
InlineKeyboardButton("Masculine", callback_data=f"gender_masculine_{message_id}"),
InlineKeyboardButton("Feminine", callback_data=f"gender_feminine_{message_id}")
)
return markup
@bot.callback_query_handler(func=lambda call: call.data.startswith("gender_"))
def handle_gender_selection(call):
gender, message_id = call.data.split("_")[1], call.data.split("_")[2]
bot.answer_callback_query(call.id, f"Selected: {gender.capitalize()}")
bot.edit_message_text("Select a zoom range:", chat_id=call.message.chat.id, message_id=call.message.id,
reply_markup=create_zoom_range_keyboard(gender, message_id))
def create_zoom_range_keyboard(gender, message_id):
markup = InlineKeyboardMarkup()
ranges = [("2–4", "2_4"), ("4–6", "4_6"), ("6–8", "6_8")]
if len(ranges) <= 4:
markup.row(*[InlineKeyboardButton(label, callback_data=f"zoom_{gender}_{data}_{message_id}") for label, data in ranges])
else:
for label, data in ranges:
markup.add(InlineKeyboardButton(label, callback_data=f"zoom_{gender}_{data}_{message_id}"))
return markup
@bot.callback_query_handler(func=lambda call: call.data.startswith("zoom_"))
def handle_zoom_range_selection(call):
_, gender, start, end, message_id = call.data.split("_")
start, end = int(start), int(end)
precise_values = [round(x, 1) for x in frange(start, end, 0.3)]
bot.edit_message_text("Select a precise pitch value:", chat_id=call.message.chat.id, message_id=call.message.id,
reply_markup=create_precise_pitch_keyboard(gender, precise_values, message_id))
def create_precise_pitch_keyboard(gender, values, message_id):
markup = InlineKeyboardMarkup()
if len(values) <= 4:
markup.row(*[InlineKeyboardButton(str(value), callback_data=f"pitch_{gender}_{value}_{message_id}") for value in values])
else:
for value in values:
markup.add(InlineKeyboardButton(str(value), callback_data=f"pitch_{gender}_{value}_{message_id}"))
return markup
@bot.callback_query_handler(func=lambda call: call.data.startswith("pitch_"))
def handle_precise_pitch_selection(call):
_, gender, pitch_value, message_id = call.data.split("_")
pitch_value = float(pitch_value)
if gender == "masculine":
pitch_value = -pitch_value
input_file_path = os.path.join(TEMP_DIR, f"{message_id}_input_audio")
if not os.path.exists(input_file_path):
bot.answer_callback_query(call.id, "File not found! Please upload a file first.")
return
def progress_message(status, percentage):
bot.edit_message_text(f"{status}\nProgress: {percentage}%", chat_id=call.message.chat.id,
message_id=call.message.id)
processed_file = process_audio(input_file_path, pitch_value, progress_message)
with open(processed_file, "rb") as audio:
bot.send_audio(call.message.chat.id, audio)
os.remove(input_file_path)
os.remove(processed_file)
bot.send_message(call.message.chat.id, "Here is your modified audio!")
def frange(start, stop, step):
while start <= stop:
yield start
start += step
print("Bot is running...")
bot.infinity_polling(skip_pending=True)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment