Skip to content
ivLis edited this page Jan 22, 2026 · 1 revision

Creating AI Addons

한국어

This guide explains how to create custom AI provider addons for ivLyrics.


Overview

AI Addons provide translation, phonetic notation, metadata translation, and TMI (Track Music Info) features. They are registered with the AIAddonManager and can be enabled/disabled by users.


Addon Structure

Basic Template

(function() {
    'use strict';

    const addon = {
        // Required: Unique identifier
        id: 'my-ai-provider',

        // Required: Display name
        name: 'My AI Provider',

        // Required: Author name
        author: 'Your Name',

        // Required: Description (string or localized object)
        description: {
            en: 'My custom AI provider for translation',
            ko: '번역을 위한 커스텀 AI 제공자'
        },

        // Required: Supported capabilities
        supports: {
            translate: true,
            metadata: true,
            tmi: false
        },

        // Optional: Settings UI
        getSettingsUI: function() {
            // Return React component or null
            return null;
        },

        // Optional: Initialize addon
        init: async function() {
            console.log('My AI Provider initialized');
        },

        // Required if supports.translate = true
        translate: async function(params) {
            // params: { lyrics, sourceLang, targetLang, mode }
            // Return: { lines: [...], error: null } or { error: 'message' }
        },

        // Required if supports.metadata = true
        translateMetadata: async function(params) {
            // params: { title, artist, lang }
            // Return: { title, artist } or null
        },

        // Required if supports.tmi = true
        generateTMI: async function(params) {
            // params: { title, artist, album, lyrics }
            // Return: { content: '...', error: null }
        }
    };

    // Wait for AIAddonManager to be available
    function register() {
        if (window.AIAddonManager) {
            window.AIAddonManager.register(addon);
        } else {
            setTimeout(register, 100);
        }
    }
    register();
})();

Required Fields

id

  • Unique identifier string
  • Use lowercase with hyphens
  • Example: 'my-ai-provider'

name

  • Display name shown in settings
  • Example: 'My AI Provider'

author

  • Creator name for credits
  • Example: 'Your Name'

description

Can be a simple string or localized object:

// Simple
description: 'Description text'

// Localized
description: {
    en: 'English description',
    ko: '한국어 설명',
    ja: '日本語の説明'
}

supports

Object defining which capabilities the addon provides:

supports: {
    translate: true,    // Lyrics translation
    metadata: true,     // Title/artist translation
    tmi: false          // Track info generation
}

Methods

translate(params)

Translate lyrics to target language.

Parameters:

{
    lyrics: [
        { text: 'Line 1', startTime: 0 },
        { text: 'Line 2', startTime: 5000 }
    ],
    sourceLang: 'ja',           // Detected source language
    targetLang: 'ko',           // User's target language
    mode: 'translate' | 'phonetic'  // Translation or romanization
}

Return:

// Success
{
    lines: [
        { text: 'Translated line 1' },
        { text: 'Translated line 2' }
    ],
    error: null
}

// Error
{
    lines: null,
    error: 'Error message'
}

translateMetadata(params)

Translate song title and artist name.

Parameters:

{
    title: 'Original Song Title',
    artist: 'Original Artist Name',
    lang: 'ko'  // Target language
}

Return:

// Success
{
    title: 'Translated Title',
    artist: 'Translated Artist'
}

// Failure
null

generateTMI(params)

Generate interesting facts about the track.

Parameters:

{
    title: 'Song Title',
    artist: 'Artist Name',
    album: 'Album Name',
    lyrics: 'Full lyrics text'
}

Return:

{
    content: 'Interesting facts about this song...',
    error: null
}

Settings UI

Provide a settings interface for user configuration:

getSettingsUI: function() {
    const React = Spicetify.React;
    const { useState, useEffect } = React;

    return function SettingsComponent() {
        const [apiKey, setApiKey] = useState('');

        useEffect(() => {
            // Load saved API key
            const saved = window.AIAddonManager.getAddonSetting(
                'my-ai-provider',
                'apiKey',
                ''
            );
            setApiKey(saved);
        }, []);

        const handleSave = () => {
            window.AIAddonManager.setAddonSetting(
                'my-ai-provider',
                'apiKey',
                apiKey
            );
        };

        return React.createElement('div', null,
            React.createElement('input', {
                type: 'password',
                value: apiKey,
                onChange: (e) => setApiKey(e.target.value),
                placeholder: 'Enter API Key'
            }),
            React.createElement('button', {
                onClick: handleSave
            }, 'Save')
        );
    };
}

Getting Settings

Use AIAddonManager to get/set addon-specific settings:

// Get setting
const apiKey = window.AIAddonManager.getAddonSetting(
    'my-ai-provider',  // Addon ID
    'apiKey',          // Setting key
    ''                 // Default value
);

// Set setting
window.AIAddonManager.setAddonSetting(
    'my-ai-provider',
    'apiKey',
    'new-value'
);

Example: Simple OpenAI Addon

(function() {
    'use strict';

    const addon = {
        id: 'my-openai',
        name: 'My OpenAI',
        author: 'Developer',
        description: 'OpenAI-based translation',
        
        supports: {
            translate: true,
            metadata: false,
            tmi: false
        },

        getSettingsUI: function() {
            // ... settings UI implementation
        },

        translate: async function(params) {
            const apiKey = window.AIAddonManager.getAddonSetting(
                'my-openai', 'apiKey', ''
            );

            if (!apiKey) {
                return { error: 'API key not configured' };
            }

            try {
                const response = await fetch(
                    'https://api.openai.com/v1/chat/completions',
                    {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json',
                            'Authorization': `Bearer ${apiKey}`
                        },
                        body: JSON.stringify({
                            model: 'gpt-3.5-turbo',
                            messages: [{
                                role: 'user',
                                content: `Translate these lyrics to ${params.targetLang}:\n${
                                    params.lyrics.map(l => l.text).join('\n')
                                }`
                            }]
                        })
                    }
                );

                const data = await response.json();
                const translated = data.choices[0].message.content;
                const lines = translated.split('\n').map(text => ({ text }));

                return { lines, error: null };
            } catch (error) {
                return { error: error.message };
            }
        }
    };

    function register() {
        if (window.AIAddonManager) {
            window.AIAddonManager.register(addon);
        } else {
            setTimeout(register, 100);
        }
    }
    register();
})();

File Placement

Place your addon file in the ivLyrics directory and add it to manifest.json:

{
    "subfiles_extension": [
        "Addon_AI_MyProvider.js"
    ]
}

Testing

  1. Add your addon file
  2. Update manifest.json
  3. Run spicetify apply
  4. Open Spotify and check Settings > AI Providers
  5. Enable your provider and test translation

Best Practices

  1. Error Handling: Always catch and return errors gracefully
  2. Rate Limiting: Implement appropriate delays for API calls
  3. Caching: Consider caching responses to reduce API usage
  4. Localization: Provide descriptions in multiple languages
  5. API Key Security: Never log or expose API keys

Related

Clone this wiki locally