Skip to content

Commit 644eca3

Browse files
author
AudD
committed
Initial release v1.4.3
0 parents  commit 644eca3

80 files changed

Lines changed: 5740 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/ci.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
permissions:
10+
contents: read
11+
12+
jobs:
13+
test:
14+
name: tests (JDK ${{ matrix.java }})
15+
runs-on: ubuntu-latest
16+
strategy:
17+
fail-fast: false
18+
matrix:
19+
java: ['11', '17', '21']
20+
steps:
21+
- uses: actions/checkout@v4
22+
- uses: actions/setup-java@v4
23+
with:
24+
distribution: temurin
25+
java-version: ${{ matrix.java }}
26+
cache: maven
27+
- name: mvn verify
28+
run: mvn -B verify
29+
- name: jar --describe-module (JPMS smoke)
30+
if: matrix.java == '21'
31+
run: |
32+
JAR=$(ls target/audd-*.jar 2>/dev/null | grep -v sources | grep -v javadoc | head -1)
33+
if [ -n "$JAR" ]; then jar --describe-module --file="$JAR"; fi

.github/workflows/contract.yml

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
name: Contract tests
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
schedule:
9+
- cron: '0 6 * * *'
10+
repository_dispatch:
11+
types: [openapi-updated]
12+
13+
permissions:
14+
contents: read
15+
issues: write
16+
17+
jobs:
18+
contract:
19+
name: validate parser against latest audd-openapi fixtures
20+
runs-on: ubuntu-latest
21+
steps:
22+
- uses: actions/checkout@v4
23+
with:
24+
path: audd-java
25+
- name: Check out audd-openapi
26+
uses: actions/checkout@v4
27+
with:
28+
repository: AudDMusic/audd-openapi
29+
path: audd-openapi
30+
ref: main
31+
- uses: actions/setup-java@v4
32+
with:
33+
distribution: temurin
34+
java-version: '21'
35+
cache: maven
36+
- name: Run contract tests
37+
working-directory: audd-java
38+
env:
39+
AUDD_OPENAPI_FIXTURES: ${{ github.workspace }}/audd-openapi/fixtures
40+
run: mvn -B test -Dtest='*ContractTest' -DfailIfNoTests=false
41+
- name: Open issue on failure (dispatched runs only)
42+
if: failure() && github.event_name == 'repository_dispatch'
43+
env:
44+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
45+
TRIGGER_SHA: ${{ github.event.client_payload.trigger_sha }}
46+
run: |
47+
gh issue create \
48+
--title "Contract drift: audd-openapi spec change broke parser" \
49+
--body "An openapi-updated dispatch (trigger SHA: $TRIGGER_SHA) caused contract tests to fail. Investigate and update parsers." \
50+
--label "contract-drift" || true

.github/workflows/release.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'audd-java/v*'
7+
8+
permissions:
9+
contents: read
10+
11+
jobs:
12+
publish:
13+
name: Build and publish to Maven Central
14+
runs-on: ubuntu-latest
15+
environment: maven-central
16+
steps:
17+
- uses: actions/checkout@v4
18+
- uses: actions/setup-java@v4
19+
with:
20+
distribution: temurin
21+
java-version: '21'
22+
cache: maven
23+
server-id: central
24+
server-username: MAVEN_CENTRAL_USERNAME
25+
server-password: MAVEN_CENTRAL_PASSWORD
26+
gpg-private-key: ${{ secrets.MAVEN_GPG_PRIVATE_KEY }}
27+
gpg-passphrase: MAVEN_GPG_PASSPHRASE
28+
- name: Verify build
29+
run: mvn -B verify
30+
- name: Deploy to Maven Central
31+
env:
32+
MAVEN_CENTRAL_USERNAME: ${{ secrets.MAVEN_CENTRAL_USERNAME }}
33+
MAVEN_CENTRAL_PASSWORD: ${{ secrets.MAVEN_CENTRAL_PASSWORD }}
34+
MAVEN_GPG_PASSPHRASE: ${{ secrets.MAVEN_GPG_PASSPHRASE }}
35+
run: mvn -B -Prelease deploy -DskipTests

.gitignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
target/
2+
*.class
3+
*.jar
4+
*.war
5+
*.ear
6+
.idea/
7+
*.iml
8+
.vscode/
9+
.settings/
10+
.classpath
11+
.project
12+
hs_err_pid*
13+
.mvn/wrapper/maven-wrapper.jar

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2026 AudD
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# audd-java — Official Java SDK for AudD
2+
3+
The official Java SDK for the [AudD music recognition API](https://audd.io).
4+
Java 11+, OkHttp transport, sync `AudD` + async `AsyncAudD` (CompletableFuture-based),
5+
forward-compatible types, cost-aware retries.
6+
7+
## Hello, AudD
8+
9+
```java
10+
import io.audd.AudD;
11+
12+
public class Hello {
13+
public static void main(String[] args) throws Exception {
14+
try (AudD audd = AudD.builder().apiToken("test").build()) {
15+
var result = audd.recognize("https://audd.tech/example.mp3");
16+
if (result != null) {
17+
System.out.println(result.artist() + "" + result.title());
18+
}
19+
}
20+
}
21+
}
22+
```
23+
24+
The public `"test"` token is capped at 10 requests; get a real one at
25+
[dashboard.audd.io](https://dashboard.audd.io/).
26+
27+
## Install
28+
29+
Maven:
30+
31+
```xml
32+
<dependency>
33+
<groupId>io.audd</groupId>
34+
<artifactId>audd</artifactId>
35+
<version>1.4.0</version>
36+
</dependency>
37+
```
38+
39+
Gradle:
40+
41+
```kotlin
42+
implementation("io.audd:audd:1.4.0")
43+
```
44+
45+
Java 11+.
46+
47+
## Capabilities
48+
49+
| Capability | SDK |
50+
|---|---|
51+
| Recognize a song (URL / file / bytes / InputStream) | `audd.recognize(source, opts)` |
52+
| Recognize a long file (enterprise) | `audd.recognizeEnterprise(source, opts)` |
53+
| Configure callback URL | `audd.streams().setCallbackUrl(url, opts)` |
54+
| Add a stream | `audd.streams().add(req)` |
55+
| List/manage streams | `audd.streams().list() / delete(...) / setUrl(...)` |
56+
| Streams (callback POST or longpoll subscription) | `audd.streams().longpoll(...)` / `Streams.parseCallback(body)` |
57+
| Tokenless longpoll (browser/widget) | `new LongpollConsumer(category)` |
58+
| Derive a longpoll category locally | `Streams.deriveLongpollCategory(token, radioId)` |
59+
60+
Sample mains will be added under [`examples/`](./examples). For now, treat the
61+
[`Hello, AudD`](#hello-audd) snippet above as the canonical starting point.
62+
63+
## Configuration
64+
65+
```java
66+
AudD audd = AudD.builder()
67+
.apiToken("your-token")
68+
.maxRetries(5)
69+
.backoffFactorMs(1000)
70+
.standardTimeoutSeconds(120)
71+
.enterpriseTimeoutSeconds(7200)
72+
.httpClient(new OkHttpClient.Builder() /* corporate proxy etc. */ .build())
73+
.onDeprecation(msg -> log.warn("audd-deprecation: {}", msg))
74+
.build();
75+
```
76+
77+
`AudD` and `AsyncAudD` are safe for concurrent use across threads. Token
78+
rotation via `setApiToken(...)` uses an `AtomicReference`; in-flight requests
79+
continue with the prior token, subsequent ones use the new one.
80+
81+
Retries are cost-aware:
82+
83+
- **READ** endpoints (`streams.list`, `streams.getCallbackUrl`): retry on
84+
408/429/5xx and connection errors.
85+
- **RECOGNITION** endpoints (`recognize`, `recognizeEnterprise`,
86+
`advanced.findLyrics`, `advanced.rawRequest`): retry on pre-upload
87+
connection failures and on 5xx. Do **not** retry on read-timeout
88+
after upload completed (cost protection).
89+
- **MUTATING** endpoints (`streams.add`, `streams.delete`, etc.): retry only
90+
on pre-upload connection failures.
91+
92+
## Error handling
93+
94+
Sealed hierarchy under `AudDException`:
95+
96+
```
97+
AudDException
98+
├── AudDApiError
99+
│ ├── AudDAuthenticationError (900, 901, 903)
100+
│ ├── AudDQuotaError (902)
101+
│ ├── AudDSubscriptionError (904, 905)
102+
│ │ └── AudDCustomCatalogAccessError
103+
│ ├── AudDInvalidRequestError (50, 51, 600/601/602, 700/701/702, 906)
104+
│ ├── AudDInvalidAudioError (300, 400, 500)
105+
│ ├── AudDRateLimitError (611)
106+
│ ├── AudDStreamLimitError (610)
107+
│ ├── AudDNotReleasedError (907)
108+
│ ├── AudDBlockedError (19, 31337)
109+
│ ├── AudDNeedsUpdateError (20)
110+
│ └── AudDServerError (100, 1000, generic 5xx)
111+
├── AudDConnectionError # network / TLS / timeout
112+
└── AudDSerializationError # 2xx response with malformed JSON
113+
```
114+
115+
## Custom catalog (advanced — read first)
116+
117+
> **This is NOT how you submit audio for music recognition.** For that, use
118+
> `audd.recognize(...)` (or `audd.recognizeEnterprise(...)` for files longer
119+
> than 25 seconds). The custom-catalog endpoint manipulates your **private
120+
> fingerprint catalog** so AudD's recognition can later identify *your own*
121+
> tracks for *your account only*. Requires special access — contact
122+
> api@audd.io if you need it enabled.
123+
124+
```java
125+
audd.customCatalog().add(146, Path.of("track.mp3"));
126+
```
127+
128+
## Advanced
129+
130+
`audd.advanced().findLyrics("query")` and `audd.advanced().rawRequest(method, params)`.
131+
`rawRequest` is the escape hatch for any AudD endpoint not yet wrapped here.
132+
133+
## Contributing / security / license
134+
135+
- Issues: <https://github.com/AudDMusic/audd-java/issues>
136+
- Security: see [SECURITY.md](./SECURITY.md)
137+
- License: MIT (see [LICENSE](./LICENSE))

SECURITY.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Security Policy
2+
3+
## Reporting a vulnerability
4+
5+
If you discover a security issue in this SDK, please email **api@audd.io** privately. Do not open a public GitHub issue for security reports.
6+
7+
We will acknowledge receipt within 2 business days and coordinate disclosure with you.
8+
9+
## Scope
10+
11+
- **In scope:** vulnerabilities in this SDK's source code.
12+
- **Out of scope:** issues in upstream dependencies (file those with the upstream maintainer), or issues in the AudD service or API itself (email **api@audd.io** with subject `AudD service: <summary>`).
13+
14+
## Hardening practices
15+
16+
This SDK never logs `api_token`, request bodies, or response bodies. The `onEvent` inspection hook receives request / response / exception lifecycle events with method, URL, HTTP status, elapsed time, and request_id — but never the token or payload bytes.
17+

0 commit comments

Comments
 (0)