get-chords / app.py
RayPac006's picture
Update app.py
a0811fa verified
import gradio as gr
from chord_extractor.extractors import Chordino
import pandas as pd
# Initialize the extractor once
chordino = Chordino()
# Minimum duration to consider a chord "real" (0.4s is usually a good sweet spot for standard tempos)
MIN_DURATION = 0.4
def format_timestamp(ts):
"""Convert seconds to mm:ss format"""
minutes = int(ts // 60)
seconds = int(ts % 60)
return f"{minutes}:{seconds:02}"
def process_audio(audio_path):
if audio_path is None:
return None, "Please upload an audio file."
try:
# Extract raw chords
extracted_chords = chordino.extract(audio_path)
if not extracted_chords:
return None, "No chords could be detected."
filtered_data = []
# Process the sequence of chords
for i in range(len(extracted_chords)):
current = extracted_chords[i]
# 1. Calculate the duration of the current chord by looking at the next chord
if i + 1 < len(extracted_chords):
duration = extracted_chords[i+1].timestamp - current.timestamp
else:
duration = 999.0 # The last chord rings out to the end of the song
# 2. Skip tiny passing notes/artifacts (unless it's the very first chord)
if duration < MIN_DURATION and i != 0:
continue
# 3. Skip extremely short 'N' (No Chord / Silence) artifacts
if current.chord == 'N' and duration < 1.0:
continue
# 4. Prevent duplicate consecutive chords in the final table
if filtered_data and filtered_data[-1][1] == current.chord:
continue
# If it passes all filters, add it to our display data
filtered_data.append([format_timestamp(current.timestamp), current.chord])
return filtered_data, f"Successfully extracted {len(filtered_data)} stable chord changes."
except Exception as e:
return None, f"Error: {str(e)}"
# Define Gradio interface
with gr.Blocks(title="Guitar Chord Extractor") as demo:
gr.Markdown("# 🎸 Guitar Chord Extractor")
gr.Markdown("Upload an audio file (mp3, wav, flac) to extract the chord progression. Fast passing tones and noise are automatically filtered out.")
with gr.Row():
with gr.Column():
audio_input = gr.Audio(label="Upload Audio", type="filepath")
submit_btn = gr.Button("Extract Chords", variant="primary")
with gr.Column():
status_output = gr.Textbox(label="Status")
chord_output = gr.Dataframe(
headers=["Timestamp", "Chord"],
datatype=["str", "str"], # 'str' is the correct Gradio datatype
label="Extracted Progression"
)
submit_btn.click(
fn=process_audio,
inputs=[audio_input],
outputs=[chord_output, status_output]
)
# Launch the app
if __name__ == "__main__":
demo.launch(server_name="0.0.0.0", server_port=7860)