PyMusicLooper

repository·master·Indexed 18 days ago

https://github.com/arkrow/pymusiclooper

A Python-based tool for finding and applying seamless loop points to audio files. It supports endless playback, exporting split segments (intro/loop/outro), extending tracks, and embedding loop metadata tags. It features a CLI for audio analysis and a Python API including the MLAudio class for audio management and the find_best_loop_points function for chroma-based loop discovery.

Tokens
9.6K
Snippets
34
Records
39
Agent score
62%

What's inside pymusiclooper

  1. Advanced loop point discovery and constraints

    master

    If the default loop detection is not sufficient, you can use advanced flags to refine the search.

    Use --brute-force to check the entire track instead of just detected beats. This is much more thorough but significantly slower (may take several minutes).

    pmusiclooper -i export-points --path "TRACK_NAME.wav" --brute-force

    Disable pruning

    By default, the program filters loop points if there are $\ge 100$ pairs. Disable this with --disable-pruning:

    pmusiclooper -i export-points --path "TRACK_NAME.wav" --disable-pruning

    Adjust loop duration constraints

    Set constraints using a multiplier of the track length or specific second values:

    # Using a multiplier (e.g., loop must be at least 85% of track)
    pmusiclooper -i split-audio --path "TRACK_NAME.flac" --min-duration-multiplier 0.85
    
    # Using specific seconds
    pmusiclooper -i split-audio --path "TRACK_NAME.flac" --min-loop-duration 120 --max-loop-duration 150

    Search near a known position

    If you know roughly where the loop should be, use --approx-loop-position <start_sec> <end_sec> to search within $\pm 2$ seconds of those points:

    pmusiclooper -i export-points --path "/path/to/track.mp3" --approx-loop-position 20 210
    pmusiclooper -i export-points --path "TRACK_NAME.wav" --brute-force
  2. Install PyMusicLooper using pipx

    master

    Using pipx isolates dependencies and is a good alternative to uv. This method requires Python and pipx to be already installed on your system.

    To install the official release:

    pipx install pymusiclooper

    To install the nightly/git version:

    pipx install git+https://github.com/arkrow/PyMusicLooper.git

    To update:

    pipx upgrade pymusiclooper
    pipx install pymusiclooper
  3. Export loop points and audio segments

    master

    PyMusicLooper provides several ways to export loop data or modified audio files. Batch processing is supported by providing a directory path instead of a file path.

    Split audio into intro, loop, and outro

    pmusiclooper -i split-audio --path "TRACK_NAME.ogg"

    Extend a track to a specific length

    Extend a track to a certain number of seconds (e.g., 3600 for one hour):

    pmusiclooper -i extend --path "TRACK_NAME.ogg" --extended-length 3600

    Export loop points to terminal

    To see the best loop points as sample points in the terminal:

    pmusiclooper -i export-points --path "/path/to/track.wav"

    To see all discovered loop points (raw format: loop_start loop_end note_difference loudness_difference score):

    pmusiclooper export-points --path "/path/to/track.wav" --alt-export-top -1

    Export loop points to a text file

    Creates a file compatible with LoopingAudioConverter (format: {loop-start} {loop-end} {filename}):

    pmusiclooper -i export-points --path "/path/to/dir/" --export-to txt

    Add loop points as metadata tags

    Write the discovered loop points into a copy of the audio file:

    pmusiclooper -i tag --path "TRACK_NAME.mp3" --tag-names LOOP_START LOOP_END
    pmusiclooper -i split-audio --path "TRACK_NAME.ogg"
  4. Install PyMusicLooper using uv (Recommended)

    master

    The recommended installation method uses uv to isolate dependencies and avoid conflicts. uv will automatically install the required Python version if it is not present.

    To install the official release:

    uv tool install pymusiclooper

    To install the nightly/git version:

    uv tool install git+https://github.com/arkrow/PyMusicLooper.git

    To update your installation:

    uv tool upgrade pymusiclooper

    If the latest Python version is not supported, you can specify a version manually:

    uv tool install pymusiclooper --python "3.12"
    uv tool install pymusiclooper
  5. Pre-requisites for PyMusicLooper

    master

    Before installing, ensure you meet the following requirements:

    • Python: Version >= 3.10 (64-bit).
    • ffmpeg: Highly recommended. It is required for loading audio from YouTube/streams (via yt-dlp) and adds support for formats like M4A/AAC, ALAC, WMA, etc. Without ffmpeg, only WAV, FLAC, Ogg/Vorbis, Ogg/Opus, and MP3 are supported.
    • Linux Users: To use the play command, you must install the PortAudio library (e.g., sudo apt install libportaudio2 on Ubuntu).
  6. Play audio files and streams

    master

    Use the play and play-tagged commands to listen to audio with seamless looping.

    Note: It is highly recommended to use the -i (interactive) flag, as the automatically chosen "best" loop point might not be perceptually ideal.

    Play from a file

    pmusiclooper -i play --path "TRACK_NAME.mp3"

    Play from a URL (YouTube/Streams)

    pmusiclooper -i play --url "https://www.youtube.com/watch?v=dQw4w9WgXcQ"

    Play using existing metadata tags

    If your file already contains loop metadata (stored as samples), use play-tagged:

    pmusiclooper play-tagged --path "TRACK_NAME.mp3" --tag-names LOOP_START LOOP_END
    pmusiclooper -i play --path "TRACK_NAME.mp3"
  7. Optimize analysis speed using approximate loop points

    master

    If you have a rough idea of where the loop should occur, providing approx_loop_start and approx_loop_end (in seconds) to find_best_loop_points() will:

    1. Skip beat analysis: This speeds up runtime by approximately 2x and significantly reduces memory consumption.
    2. Restrict search range: The algorithm will only check beats within +/- 2 seconds of your provided approximate points.

    Note: If you specify one approximate point, you must specify both.

  8. Use brute force mode for exhaustive search

    master

    By setting brute_force=True in find_best_loop_points(), the analysis ignores detected beats and checks every single frame in the track.

    Warning: This operation is computationally expensive and may take several minutes to complete. The program may appear to hang during this process.

  9. Configure logging verbosity for YouTube downloads

    master

    The YoutubeDownloader uses an internal YtdLogger class to handle output from yt-dlp. You can control the level of detail printed to the console by setting the PML_VERBOSE environment variable.

    • If PML_VERBOSE is NOT set: The logger suppresses most debug information and only prints critical updates (like [ExtractAudio] or [download] progress) to keep the console clean.
    • If PML_VERBOSE is set: The logger will print all messages, including warnings and general info, which is useful for debugging.
    # To enable verbose logging for debugging
    export PML_VERBOSE=1
    python your_script.py
  10. Manage loop metadata with export_tags() and read_tags()

    master

    You can embed loop points directly into audio file metadata using export_tags() and retrieve them using read_tags().

    Writing Tags

    export_tags() creates a copy of the source file with the specified loop points added as metadata tags.

    Parameters:

    • loop_start (int): Start index in samples.
    • loop_end (int): End index in samples.
    • loop_start_tag (str): The name of the tag to use for the start (e.g., "LOOPSTART").
    • loop_end_tag (str): The name of the tag to use for the end (e.g., "LOOPEND").
    • is_offset (bool, optional): If True, the second tag is treated as a relative length (offset) rather than an absolute position. Auto-detected based on tag name if None.
    • output_dir (str, optional): Directory to save the tagged file.

    Reading Tags

    read_tags() extracts loop points from the file's metadata.

    Parameters:

    • loop_start_tag (str, optional): Tag name for start. If None, it attempts to auto-detect using known patterns.
    • loop_end_tag (str, optional): Tag name for end. If None, it attempts to auto-detect.
    • is_offset (bool, optional): Whether to parse the second tag as a relative length/offset.

    Returns (read_tags):

    • Tuple[int, int]: A tuple of (real_loop_start, real_loop_end) in samples.
    # Writing tags
    looper.export_tags(
        loop_start=44100,
        loop_end=88200,
        loop_start_tag="LOOPSTART",
        loop_end_tag="LOOPEND"
    )
    
    # Reading tags
    start, end = looper.read_tags("LOOPSTART", "LOOPEND")
  11. Download audio from a URL with download_audio()

    master

    The download_audio function uses YoutubeDownloader (via yt-dlp) to download audio from a provided URL and save it to a specific directory. It returns the absolute filepath of the downloaded audio file.

    from pymusiclooper.utils import download_audio
    
    url = "https://www.youtube.com/watch?v=example"
    output_dir = "./downloads"
    
    # Downloads the audio and returns the path to the file
    audio_filepath = download_audio(url, output_dir)
    print(f"Downloaded to: {audio_filepath}")