OmniDAW API to JSON-RPC 2.0 przez lokalne gniazdo TCP, jeden obiekt JSON w linii. Wszystko, co potrafi otworzyć gniazdo i sparsować JSON, może sterować Omni. Ta strona to kompletna specyfikacja; referencja metod wymienia, co można wywołać.
Transport
- Adres: TCP wyłącznie na
127.0.0.1. Połączenia z innych adresów są odrzucane. - Ramkowanie: jeden obiekt JSON-RPC 2.0 w linii, UTF-8, każda linia kończy się
\n. Odpowiedzi wracają po kolei, jedna na żądanie. - Limity: linia dłuższa niż 8 MiB zamyka połączenie. Naraz obsługiwanych jest do 8 połączeń.
- Powiadomienia: żądanie bez
idjest wykonywane, ale nie dostaje odpowiedzi.
Znalezienie Omni
Gdy API jest włączone, Omni zapisuje api/endpoint.json w swoim folderze ustawień i usuwa go przy zamknięciu:
{
"protocol": "omnidaw-api",
"api_version": "0.21.0",
"host": "127.0.0.1",
"port": 50123,
"token": "9f2c...64 znaki szesnastkowe...",
"pid": 4242
}
| System | Folder ustawień |
|---|---|
| Windows | %APPDATA%\omni |
| macOS | ~/Library/Application Support/omni |
| Linux | $XDG_CONFIG_HOME/omni, a jeśli brak, ~/.config/omni |
Port jest losowy, chyba że przed startem Omni ustawisz zmienną środowiskową OMNI_API_PORT. Klient może pominąć plik, ustawiając OMNI_API_ENDPOINT=host:port razem z OMNI_API_TOKEN, na przykład w testach. Token jest nowy przy każdym uruchomieniu, a plik może czytać tylko użytkownik, który uruchomił Omni.
Uścisk dłoni
Pierwszym wywołaniem na każdym połączeniu musi być api.hello z tokenem. Dopóki się nie powiedzie, wszystko poza api.ping dostaje odpowiedź unauthorized.
{"jsonrpc":"2.0","id":1,"method":"api.hello","params":{"token":"9f2c...","api_version":"0.21.0","client":{"name":"my-tool","version":"1.0"}}}
{"jsonrpc":"2.0","id":1,"result":{"protocol":"omnidaw-api","api_version":"0.21.0","app":{"name":"Omni","version":"0.1.0"},"method_count":102,"capabilities":["jobs","analysis","render","plugins","audio"]}}
api_version w żądaniu to wersja, względem której Twój klient został zbudowany. Jeśli nie jest zgodna, dostaniesz incompatible (zob. Wersjonowanie). client to dowolny tekst pokazywany w logu Omni.
Capabilities
capabilities mówi klientowi, co ten host oferuje poza listą metod, żeby mógł się dostosować bez prób i błędów:
| Capability | Znaczenie |
|---|---|
jobs | Długie operacje działają jako zadania (jobs.get, jobs.wait) |
analysis | Nagranie i analiza mastera lub toru |
render | Eksport offline i stemy, szybciej niż w czasie rzeczywistym |
plugins | Zewnętrzne instrumenty i efekty VST3 oraz CLAP |
audio | Klipy audio: sampler, slicer, transkrypcja, rozdzielanie stemów |
files | Obecne tylko wtedy, gdy użytkownik zezwolił klientom na czytanie plików audio (zob. Bezpieczeństwo) |
Metody spoza katalogu
Trzy metody należą do samego połączenia i nie dotykają projektu:
| Metoda | Robi |
|---|---|
api.hello | Uścisk dłoni opisany wyżej |
api.methods | Kompletny dokument katalogu |
api.ping | Odpowiada "pong"; dozwolone przed uściskiem dłoni. Służy do sprawdzenia bezczynnego połączenia |
Dokument katalogu
api.methods zwraca wszystko, czego klient potrzebuje, żeby przedstawić API bez wpisywania go na sztywno:
{
"protocol": "omnidaw-api",
"api_version": "0.21.0",
"units": { "time": "beats (quarter notes)", "level": "dB / dBFS, null = silence", "...": "..." },
"errors": [ { "code": -32602, "name": "invalid_params" }, "..." ],
"methods": [ { "name": "tracks.update", "...": "..." } ]
}
Każdy wpis methods ma:
| Pole | Znaczenie |
|---|---|
name | domena.czasownik, snake_case, na przykład clips.write_midi |
domain | Część przed kropką |
title | Krótki tytuł dla człowieka |
summary | Opis napisany dla modelu językowego: co robi, co przekazać, czego się spodziewać |
effect | read, control, edit, destructive lub history (zob. niżej) |
idempotent | Czy powtórzenie wywołania z tymi samymi parametrami nic więcej nie zmienia |
since | Wersja API, w której metoda się pojawiła |
params | Schemat JSON parametrów (obiekty zamknięte, zakresy, enumy, elementy zagnieżdżone) |
example | Obiekt parametrów, który jest przyjmowany bez zmian |
Serwer MCP zamienia każdy wpis w narzędzie; Budowa serwera MCP pokazuje jak.
Żądania, wyniki i błędy
Żądanie:
{"jsonrpc":"2.0","id":7,"method":"tracks.update","params":{"track":0,"volume_db":-6}}
Udana odpowiedź niesie result, nieudana error:
{"jsonrpc":"2.0","id":7,"error":{"code":-32003,"message":"slot 0 holds no audio (audio.import a file first)"}}
error.data jest opcjonalne. Kody to kody JSON-RPC plus kody Omni:
| Kod | Nazwa | Kiedy |
|---|---|---|
| -32700 | parse_error | Linia nie jest JSON-em |
| -32600 | invalid_request | To nie jest żądanie JSON-RPC 2.0 |
| -32601 | method_not_found | Nieznana metoda |
| -32602 | invalid_params | Parametry nie pasują do schematu lub zakresu; nic nie zostało zmienione |
| -32603 | internal | Błąd w Omni |
| -32001 | unauthorized | Brak udanego api.hello na tym połączeniu |
| -32002 | not_found | Tor, slot, klip lub urządzenie nie istnieje |
| -32003 | invalid_state | Istnieje, ale nie może tego zrobić (nuty na torze audio, brak wczytanego audio) |
| -32004 | busy | Omni nie odpowiedziało w czasie albo trwa już eksport lub nagranie |
| -32005 | incompatible | Wersje API się nie zgadzają |
| -32006 | unavailable | Silnik audio nie działa |
Komunikaty błędów są pisane tak, by czytał je model: mówią, co było nie tak, a tam, gdzie to pomaga, jakiej metody użyć zamiast tej. Przekazuj je dalej bez zmian.
Konwencje
| Rzecz | Reguła |
|---|---|
| Nazwy metod | domena.czasownik, snake_case. Nazwa narzędzia MCP zamienia kropkę na podkreślnik |
| Czas | Zawsze w beatach (ćwierćnutach). Takt 4/4 to 4 beaty. Sekundy pojawiają się tylko tam, gdzie zaznaczono (długość nagrania, pozycje w pliku audio) |
| Poziomy | dB lub dBFS. Cisza albo „niezmierzone” to null, nigdy minus nieskończoność |
| Głośność | LUFS (EBU R128), true peak w dBTP, zakres głośności w LU |
| Panorama | od -1 (lewo) do +1 (prawo) |
| Wysokość dźwięku | Numer nuty MIDI, 60 to środkowe C |
| Parametry | Obiekty zamknięte. Nieznane lub źle napisane pole to invalid_params, nigdy nie jest ignorowane. Wszystko jest sprawdzane, zanim cokolwiek się zmieni |
| Wyniki | Otwarte. Klienci muszą ignorować pola, których nie znają; nowe wersje dodają pola |
Odniesienia
- Tor:
id(UUID jako tekst ztracks.list, stabilny) albo 0-bazowyindex(przesuwa się, gdy tory są dodawane lub przesuwane). Preferuj id. - Slot: 0-bazowy slot klipu na torze, czyli wiersz sceny siatki sesji.
- Łańcuch efektów:
{"track": <id lub index>}dla insertów toru,{"return_bus": <index>}albo napis"master". Slot w łańcuchu to 0-bazowa pozycja w kolejności sygnału. - Klucz parametru:
instrument:<id>dla parametru instrumentu toru ifx:<slot>:<index>dla insertu, tak jak zwracaparams.list.automation.writeprzyjmuje te same klucze orazvolumeipan.
Efekty i cofanie
Każda metoda deklaruje efekt. Klient na tej podstawie decyduje o uprawnieniach, potwierdzeniach i adnotacjach MCP.
| Efekt | Znaczenie | Cofanie |
|---|---|---|
read | Czyta stan, nic nie zmienia | niepotrzebne |
control | Zmienia stan na żywo, który nie jest danymi projektu: transport, uruchamianie klipów, nagrania, eksporty | nie jest zapisywane |
edit | Zmienia projekt | jeden krok w Historii Cofania Omni z etykietą API: <tytuł> |
destructive | Usuwa zawartość | jeden krok |
history | Same edit.undo i edit.redo | brak |
Skoro każda edycja to zwykły krok historii, człowiek cofa to, co zrobił asystent, przez Ctrl+Z, a asystent może zrobić to samo przez edit.undo. Wywołanie, które edytuje wiele rzeczy naraz, na przykład arrangement.build_song, to nadal jeden krok.
Zadania
Praca trwająca sekundy (nagranie, eksport, transkrypcja, rozdzielanie stemów) nie blokuje połączenia. Wywołanie wraca od razu:
{"jsonrpc":"2.0","id":9,"result":{"job":3}}
Potem pytasz o wynik:
{"jsonrpc":"2.0","id":10,"method":"jobs.wait","params":{"job":3,"timeout_seconds":9}}
jobs.wait wraca, gdy zadanie się skończy albo po najwyżej 9 sekundach, co nastąpi wcześniej; wywołuj je ponownie, dopóki state to running. jobs.get zwraca bieżący stan natychmiast. Oba są obsługiwane bez udziału wątku UI Omni, więc czekanie nie spowalnia aplikacji. Zadanie ma:
| Pole | Znaczenie |
|---|---|
job | Id zadania |
kind | Metoda, która je rozpoczęła, na przykład analysis.capture |
state | running, done lub failed |
progress | od 0 do 1 |
result | Wynik po zakończeniu: dla nagrania analiza, dla eksportu ścieżka pliku i analiza zapisanego pliku |
error | Powód po failed, w przeciwnym razie null |
Naraz może działać tylko jedno nagranie i jeden eksport; drugie dostaje odpowiedź busy.
Limity czasu i ponawianie
- Wywołanie czeka na wątek UI Omni najwyżej 10 sekund. Jeśli Omni jest zajęte (na przykład otwarte jest okno modalne), odpowiedzią jest
busy; spróbuj ponownie, gdy się zwolni. - Jeśli połączenie zerwie się w trakcie wywołania, nie wiesz, czy
editsię wykonał. Nie wysyłaj go na ślepo ponownie: najpierw odczytaj stan (tracks.list,clips.list,arrangement.get) i zdecyduj. Odczyty i idempotentne edycje można bezpiecznie powtarzać. - Połącz się ponownie po restarcie Omni: przeczytaj
endpoint.jsonjeszcze raz, bo port i token się zmieniają. - Wyślij
api.pingprzed ponownym użyciem połączenia, które było bezczynne.
Wersjonowanie
Wersja to major.minor.patch. Reguła jest prosta:
- Klient zbudowany względem wersji A działa z hostem w wersji B, gdy numery major są równe, a B nie jest starsze od A.
- Wersje minor tylko dodają metody i pola. W obrębie jednej wersji major nic nie jest usuwane ani zmieniane tak, by zepsuć starszego klienta.
- Dlatego: ignoruj nieznane pola wyników i buduj listę narzędzi z
api.methodsprzy starcie zamiast wpisywać ją na sztywno, a każdą nową metodę dostaniesz za darmo.
since w każdym wpisie katalogu mówi, w której wersji metoda się pojawiła.
Wypróbuj ręcznie
Nie potrzebujesz niczego poza narzędziem TCP. W PowerShellu odczytaj token:
$ep = Get-Content "$env:APPDATA\omni\api\endpoint.json" | ConvertFrom-Json
$ep.port; $ep.token
Połącz się dowolnym liniowym klientem TCP (ncat 127.0.0.1 <port> albo telnet z lokalnym echem), wklej linię api.hello ze swoim tokenem, a potem:
{"jsonrpc":"2.0","id":2,"method":"theory.scale","params":{"root":"A","mode":"minor"}}
