kestra-io / kestra-io/plugin-sonilo
Add Sonilo Plugin
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 0
- Forks
- 0
- Avg merge
- 12h 56m
- Merged PRs (30d)
- 3
Description
Summary
Sonilo (https://platform.sonilo.com) is an AI video-to-music and sound-design API: given a video, it generates original, production-ready music or sound effects synced to the video's scenes, cuts, and emotional arc, with no manual editing. A Kestra plugin lets flows call Sonilo directly after a video is produced or ingested — e.g. score a completed video with a matched soundtrack as part of an automated delivery pipeline, with no custom scripting task in between.
Motivation
Teams currently automating video delivery pipelines have no first-class way to attach a matched soundtrack or sound design step to a flow — they either script raw HTTP calls or handle audio matching manually outside Kestra. A Sonilo plugin lets a flow react to a completed-video event (upload, render-finished webhook, scheduled batch) and produce a scored asset in the same execution, before handoff to downstream delivery/publishing tasks. This fits alongside Kestra's existing media/AI-generation style plugins (submit job, poll or stream for the result).
Context
No parent issue or prior discussion found — this is a new integration proposal. Sonilo's async job shape (submit → stream NDJSON or poll a task id) matches the "submit + poll for completion" pattern used by other Kestra plugins that wrap async AI/media-generation APIs; use one of those as a structural reference during implementation.
API Reference
- Official docs: https://platform.sonilo.com/docs (also available in French at https://platform.sonilo.com/fr/docs)
- Authentication: Bearer API key —
Authorization: Bearer sk_<api_key>, generated from the Sonilo dashboard - Base URL pattern:
https://api.sonilo.com/v1/ - SDK / client library: none official found — use Kestra's internal HTTP client
Note for the developer: endpoint paths below were extracted from the docs site via automated page summarization, not read verbatim. Confirm exact paths, request/response shapes, and whether a webhook/callback mechanism exists (none was found during research) against https://platform.sonilo.com/docs before implementation.
POST /v1/video-to-music— generate a soundtrack matched to an input video (sync stream orasyncmode returning a task id)POST /v1/text-to-music— generate music from a text promptPOST /v1/video-to-sfx— generate sound effects matched to an input video (async, returns a task id)POST /v1/text-to-sfx— generate sound effects from a text prompt (async, returns a task id)POST /v1/audio-ducking— mix a voice track with background music/sfxGET /v1/tasks/{task_id}— poll the status/result of an async generation task
Gradle Dependencies
No additional Gradle dependencies required — Sonilo has no official Java SDK, and its API is plain REST/JSON, so implement it with Kestra's internal HTTP client (io.kestra.core.http.client) and core Jackson serializers.
Kestra framework inclusions (do not add as dependencies):
Kestra's internal HTTP client and Jackson serializers are provided by the framework. Only list an explicit HTTP dependency when an official SDK is required — never list OkHttp, Apache HttpComponents, orjava.net.httpwrappers.
Plugin Structure
- Repository:
plugin-sonilo - Namespace:
io.kestra.plugin.sonilo - Sub-plugins: none — flat package, consistent with the existing scaffold
- Categories:
BUSINESS
Task class naming: task class names must not repeat the plugin or package name as a
prefix or suffix. Use concise action names:GenerateMusicFromVideo,GenerateMusicFromText,
GenerateSfxFromVideo,GenerateSfxFromText,DuckAudio,Trigger— notSoniloGenerateMusic,
GenerateMusicSonilo, etc.
Suggested Tasks
- Implement an
AbstractSonilobase class holding theapiToken(secret) andbaseUrlconnection properties, shared by every task and the trigger GenerateMusicFromVideo—POST /v1/video-to-music, input video viaProperty<Data>or internal-storage URI, output the generated audio to internal storageGenerateMusicFromText—POST /v1/text-to-musicGenerateSfxFromVideo—POST /v1/video-to-sfxGenerateSfxFromText—POST /v1/text-to-sfxDuckAudio—POST /v1/audio-ducking, mixing a voice track with a music/sfx track- Add a polling
Triggerthat watches a submitted async task id (GET /v1/tasks/{task_id}) and fires anExecutiononce it reaches a terminal (completed/failed) state - Write unit + integration tests with WireMock (no official Sonilo Testcontainers image exists)
- Add
package-info.javawith@PluginSubGroup(category = PluginSubGroup.PluginCategory.BUSINESS) - Add
metadata/index.yamland plugin icon SVG - Add YAML examples and the package-level how-to doc (
doc/io.kestra.plugin.sonilo.md)
YAML Examples
Example 1 — Generate a soundtrack for a rendered video
id: score_completed_video
namespace: company.media
inputs:
- id: video_uri
type: STRING
tasks:
- id: generate_music
type: io.kestra.plugin.sonilo.GenerateMusicFromVideo
apiToken: "{{ secret('SONILO_API_TOKEN') }}"
video: "{{ inputs.video_uri }}"
Example 2 — Generate sound effects from a text prompt and log the result
id: generate_sfx
namespace: company.media
tasks:
- id: generate_sfx
type: io.kestra.plugin.sonilo.GenerateSfxFromText
apiToken: "{{ secret('SONILO_API_TOKEN') }}"
prompt: "Footsteps on gravel, approaching camera"
- id: log_result
type: io.kestra.plugin.core.log.Log
message: "Generated SFX available at {{ outputs.generate_sfx.audioUri }}"
Example 3 — React when an async Sonilo generation task completes
id: on_sonilo_task_complete
namespace: company.media
triggers:
- id: wait_for_task
type: io.kestra.plugin.sonilo.Trigger
apiToken: "{{ secret('SONILO_API_TOKEN') }}"
taskId: "{{ trigger.taskId }}"
interval: PT30S
tasks:
- id: handle_result
type: io.kestra.plugin.core.log.Log
message: "Sonilo task {{ trigger.taskId }} finished: {{ trigger.status }}"
Acceptance Criteria
Functional
- Authentication task / abstract base class implemented
- Core generation tasks for each resource group (music, sfx, ducking)
- At least one polling trigger
- Unit + integration tests pass (
./gradlew test) - Build passes with
./gradlew build
Kestra Plugin Coding Standards
- HTTP calls use Kestra's internal HTTP client (
io.kestra.core.http.client) — no OkHttp, Apache HttpClient, or similar - All new properties use
Property<T>— no legacy@PluginProperty(dynamic = true)on new code - Secret/credential properties (
apiToken) annotated with@PluginProperty(secret = true)and@ToString.Exclude - Every property and output has a
@Schemaannotation - Task classes carry the five mandatory Lombok annotations (
@SuperBuilder,@ToString,@EqualsAndHashCode,@Getter,@NoArgsConstructor) - Logging via
runContext.logger()only - JSON serialization uses Jackson mappers from
io.kestra.core.serializers - All
Property<T>fields support Kestra expression language (template rendering)
Documentation & Structure
-
@Plugin(examples = ...)entries each setfull = truewith a complete runnable flow (id + namespace + tasks/triggers) - Sensitive values in examples use
{{ secret('SECRET_NAME') }} -
package-info.javawith@PluginSubGroup(category = PluginSubGroup.PluginCategory.BUSINESS) -
metadata/index.yamland plugin icon SVG present
Repository Setup Checklist
1. Add to Sanity check page
Add this plugin to the Sanity check Notion page.
2. Run scoped Terraform apply
Run the following from infra/terraform/github:
terraform apply \
-target='github_repository.repo["plugin-sonilo"]' \
-target='github_issue_labels.plugins["plugin-sonilo"]' \
-target='github_repository_ruleset.branch["plugin-sonilo"]'
Notes for the developer
- No webhook/callback mechanism was found in the publicly available docs — the trigger must poll
GET /v1/tasks/{task_id}rather than react to a push notification. Confirm this against the docs; if a webhook exists, prefer aRealtimeTriggerinstead. - Sonilo is self-serve, pay-as-you-go (Stripe-billed credits, no free tier, no sales gate for basic access) — this is why it's proposed as an OSS plugin (
plugin-sonilo, already the current repository) rather than EE. - Exact endpoint paths, request/response payloads, and error formats should be re-verified directly against https://platform.sonilo.com/docs before implementation — the research pass here used automated page summarization, not a verbatim read.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
First verify Sonilo's endpoint paths, request/response shapes, and callback support in the linked API documentation, then inspect existing Kestra plugins that use submit-and-poll flows. Implement the listed tasks and polling Trigger with WireMock unit and integration coverage, and run ./gradlew test and ./gradlew build. Done also requires package-info.java, metadata/index.yaml, the icon SVG, YAML examples, and doc/io.kestra.plugin.sonilo.md.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- api, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100