Marking

Cobalstamp adds watermarks to audio (marking) and finds watermarks in audio (detection). Marking embeds the watermark locally on your machine and registers the mark on the server. Detection sends the audio to the server, which looks for registered marks in it.

Both operations work with mono audio as a numpy array of type float32, with amplitudes in [-1, 1].

Minimal example

import numpy as np
import soundfile
import cobalstamp

# Load the audio as a float32 signal in [-1, 1].
wav, fs = soundfile.read("input.wav", dtype="float32")

# Add a watermark and register it.
marked, info = cobalstamp.mark(wav, fs, is_ai=True)
print(info)

# Detect a watermark. The audio is sent to the server, which looks
# for registered marks in it.
result = cobalstamp.detect(marked, fs)
print(result)

is_test

Marks made with is_test=True (the only accepted value at this time) belong to a test session that can be forgotten with cobalstamp.forget(). Permanent sessions (is_test=False) are not accepted by mark() at this time.

API reference

All the functions and attributes below are available at the top level of the cobalstamp module (import cobalstamp).

Watermarking

cobalstamp.mark(wav, fs, is_ai, ai_type=None, is_test=True, clip_fn='compress')

Mark an audio signal with a Cobalstamp watermark and register it on the server.

Parameters:
  • wav – Input audio signal. A numpy array of type float32 or float64, with amplitudes in [-1, 1]. Only one-dimensional mono audio is accepted for now.

  • fs (float) – Sampling rate of the audio signal in Hz.

  • is_ai (bool) – True when declaring that the audio is created using AI, False otherwise.

  • ai_type – The AI type (optional, default None): "generated" when the audio is AI-generated (ex. text-to-audio), "transformed" when it is produced by an AI transformation process (audio-to-audio). Ignored when is_ai is False.

  • is_test (bool) – Test-mode flag (default True). Test sessions (is_test=True) can be forgotten with cobalstamp.forget(). is_test=False is not accepted at this time.

  • clip_fn – Protects the marked audio from exceeding [-1, 1], where an export would produce harsh clipping. "compress" (default) applies a soft compression to the samples near full scale only; the rest of the audio is left unchanged. "rescale" slightly lowers the level of the whole marked audio so that it stays within [-1, 1] (a fraction of a decibel, and only when the marked audio would exceed full scale). None disables the protection: the marked audio may then exceed [-1, 1].

Returns:

A tuple of two elements:

  • The watermarked audio signal, as a one-dimensional float32 numpy array.

  • An info dictionary with:

    • "result": the marking outcome, "marked" when the mark was embedded and registered.

    • "mark_id": the public mark id of this marking (a UUID). Present when your plan exposes the mark id; omitted otherwise.

    • "is_test": the test-mode flag of this marking.

cobalstamp.detect(wav, fs)

Detect a Cobalstamp watermark in an audio signal. In most cases the full audio is not uploaded to the server. The server returns its verdict as soon as possible. When the verdict is pending it will be made available as soon as possible by a subsequent call on the same audio.

Parameters:
  • wav – Input audio signal (numpy array, float32, [-1, 1]; mono only).

  • fs (float) – Sampling rate in Hz.

Returns:

The server’s verdict as a dictionary, one of:

{"marked": True, "ppid": str, "is_ai": bool|null, "ai_type": str|null, "is_test": bool, "mark_id": str} when a registered mark is verified — ppid is the public provider identifier of the entity that marked the audio; is_ai says whether they declared the audio AI-related (True / False); ai_type is "generated" / "transformed" when the mark specifies a type, else None (including when is_ai is True with an unspecified type); is_test says the mark is a test mark; mark_id is the mark id of the verified marking (the id cobalstamp.mark() returns), present when your plan exposes the mark id, omitted otherwise.

{"marked": None, "pending": "modified_marks"} when the server runs an extended search in the background, and the final verdict is available on a subsequent detection of the same audio, as soon as possible.

{"marked": False} when no registered mark is found.

cobalstamp.forget(id)

Forget a registered test mark on the server, freeing the marked audio so it can be marked again (mainly for testing purpose).

This only applies to marks made with is_test=True. Marks made with is_test=False are never affected by this function.

Parameters:

id – The mark id to forget (the "mark_id" value returned by cobalstamp.mark()), or "all" to forget all the test marks belonging to the account.

Returns:

The number of forgotten test marks with this call.

Environment variables

  • COBALSTAMP_KEY: the API key (license token). It must start with api_ and be exactly 68 characters long. Create a key at https://www.cobalstamp.dev/app/api-keys

  • COBALSTAMP_TIMEOUT: timeout in seconds for the connections to the server. It is applied when the SDK session starts, i.e. before the first call to the server, so it is in effect for the login (for example export COBALSTAMP_TIMEOUT=20 on a slow connection, see Slow connection).