Oferta de lanzamiento: Los planes Creator y Business tienen descuento por tiempo limitado. Ver precios

Integración móvil

Usa la API de ADN con claves API Client-Side desde tu app iOS, Android o Flutter. Reproduce y sube archivos con elementos multimedia nativos.

Ideal para

Apps iOS, Android y Flutter. La configuración tarda unos 30 minutos.

Reproducir pistas

Crea sesiones de reproducción y reproduce audio con players multimedia nativos.

Llama a la API de reproducción de ADN directamente desde tu app móvil usando una clave API Client-Side. Crea sesiones de reproducción, obtén URLs de variante firmadas y reproduce audio con players multimedia nativos.

1. Crear una clave API Client-Side Player

En Settings → API Keys, crea una clave Client-Side Player. Limítala a las variantes y el contenido al que tu app móvil debería acceder.

2. Crear una sesión de reproducción

import Foundation

struct PlaySessionRequest: Encodable {
    let collectionId: String
    let variants: [String]
    let isDownloadable: Bool
    let expiresIn: Int
    enum CodingKeys: String, CodingKey {
        case collectionId = "collection_id"; case variants
        case isDownloadable = "is_downloadable"; case expiresIn = "expires_in"
    }
}
struct PlaySessionResponse: Decodable {
    let playSessionId: String
    let tracks: [Track]
    enum CodingKeys: String, CodingKey { case playSessionId = "play_session_id"; case tracks }
    struct Track: Decodable { let id: String }
}

func createPlaySession() async throws -> (playSessionId: String, tracks: [PlaySessionResponse.Track]) {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/play_session/collection")!)
    request.httpMethod = "POST"
    request.setValue("Bearer CLIENT-SIDE-PLAYER-API-KEY", forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    let encoder = JSONEncoder()
    encoder.keyEncodingStrategy = .convertToSnakeCase
    request.httpBody = try encoder.encode(PlaySessionRequest(
        collectionId: "COLLECTION-ID", variants: ["hq", "lq"], isDownloadable: false, expiresIn: 3600))
    let (data, _) = try await URLSession.shared.data(for: request)
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let session = try decoder.decode(PlaySessionResponse.self, from: data)
    return (session.playSessionId, session.tracks)
}

3. Obtener URLs de variante de pista

struct TrackVariantsResponse: Decodable {
    let variants: [Variant]
    struct Variant: Decodable {
        let url: String
        let variant: VariantIndex
        struct VariantIndex: Decodable { let id: String }
    }
}

// No auth needed — the session ID acts as a bearer token
func getAudioUrl(playSessionId: String, trackId: String) async throws -> String {
    let url = URL(string: "https://api.audiodelivery.net/v1/play/\(playSessionId)/\(trackId)")!
    let (data, _) = try await URLSession.shared.data(from: url)
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let res = try decoder.decode(TrackVariantsResponse.self, from: data)
    let hq = res.variants.first { $0.variant.id == "hq" }!
    return hq.url
}

4. Reproducir con el player nativo

import AVFoundation

let player = AVPlayer(url: URL(string: audioUrl)!)
player.play()

La URL firmada funciona con cualquier player multimedia nativo. ADN gestiona la entrega CDN y la verificación de URL.

Datos de forma de onda

ADN genera automáticamente datos de forma de onda RMS normalizados (320 muestras) para cada pista. El campo levels en la respuesta de la pista contiene los datos — úsalos para renderizar formas de onda en tu propio player, o genera formas de onda personalizadas mediante el tipo de variante Audio Analysis.

Imágenes de portada y colores de tema

ADN analiza cada pista subida en busca de arte de portada incrustado y lo pone disponible como cover_image en la respuesta de la pista (en tamaños icon/small/regular/large). También puedes subir una imagen de portada por separado vía la API. Cuando hay una imagen de portada, ADN extrae una paleta de colores y selecciona un player_color principal — úsalos para estilizar la UI de tu player. Junto a él, las respuestas incluyen player_color_light y player_color_dark, variantes ajustadas por contraste para dibujar el color sobre fondos claros y oscuros respectivamente. El array completo theme contiene todos los colores extraídos con valores hex, área, luminosidad y saturación.

Subir pistas

Sube archivos de audio desde apps nativas usando la API de subida de ADN.

Llama a la API de subida de ADN directamente desde tu app móvil usando una clave API Client-Side. Crea sesiones de subida, obtén URLs prefirmadas y sube archivos de audio — todo desde código nativo.

1. Crear una clave API Client-Side Upload

Inicia sesión en ADN, ve a Settings → API Keys y crea una clave Client-Side Upload. Limítala a la colección a la que tu app debería subir.

2. Crear una sesión de subida

import Foundation

struct UploadSessionRequest: Encodable {
    let collectionId: String
    let expiresIn: Int
    enum CodingKeys: String, CodingKey { case collectionId = "collection_id"; case expiresIn = "expires_in" }
}
struct UploadSessionResponse: Decodable {
    let uploadSession: UploadSession
    enum CodingKeys: String, CodingKey { case uploadSession = "upload_session" }
    struct UploadSession: Decodable { let id: String }
}

func createUploadSession() async throws -> String {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/upload_session")!)
    request.httpMethod = "POST"
    request.setValue("Bearer CLIENT-SIDE-UPLOAD-API-KEY", forHTTPHeaderField: "Authorization")
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    let encoder = JSONEncoder()
    encoder.keyEncodingStrategy = .convertToSnakeCase
    request.httpBody = try encoder.encode(UploadSessionRequest(collectionId: "COLLECTION-ID", expiresIn: 3600))
    let (data, _) = try await URLSession.shared.data(for: request)
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let session = try decoder.decode(UploadSessionResponse.self, from: data)
    return session.uploadSession.id
}

3. Obtener una URL de subida de pista

struct TrackUploadRequest: Encodable {
    let fileName: String
    enum CodingKeys: String, CodingKey { case fileName = "file_name" }
}
struct TrackUploadResponse: Decodable {
    let trackUpload: TrackUpload
    enum CodingKeys: String, CodingKey { case trackUpload = "track_upload" }
    struct TrackUpload: Decodable { let uploadUrl: String; let method: String
        enum CodingKeys: String, CodingKey { case uploadUrl = "upload_url"; case method }
    }
}

func getTrackUploadUrl(sessionId: String) async throws -> (url: String, method: String) {
    var request = URLRequest(url: URL(string: "https://api.audiodelivery.net/v1/upload/\(sessionId)/track")!)
    request.httpMethod = "POST"
    request.setValue("application/json", forHTTPHeaderField: "Content-Type")
    let encoder = JSONEncoder()
    encoder.keyEncodingStrategy = .convertToSnakeCase
    request.httpBody = try encoder.encode(TrackUploadRequest(fileName: "recording.m4a"))
    let (data, _) = try await URLSession.shared.data(for: request)
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    let res = try decoder.decode(TrackUploadResponse.self, from: data)
    return (res.trackUpload.uploadUrl, res.trackUpload.method)
}

4. Subir el archivo

// Prefer streaming for large files instead of loading into memory
func uploadAudio(fileURL: URL, uploadURL: URL, method: String) async throws {
    var request = URLRequest(url: uploadURL)
    request.httpMethod = method
    request.setValue("audio/mp4", forHTTPHeaderField: "Content-Type")
    request.httpBodyStream = InputStream(url: fileURL)
    let (_, uploadResponse) = try await URLSession.shared.data(for: request)
    let httpResponse = uploadResponse as! HTTPURLResponse
    print("Upload status: \(httpResponse.statusCode)") // 200 on success
}

Repite los pasos 3 y 4 por cada archivo — cada pista necesita su propia solicitud de subida y URL firmada. También puedes incluir un objeto anidado track al crear la sesión para crear la primera pista de antemano, y luego usar el paso 3 para cualquier archivo adicional.

5. Esperar a que la pista esté lista

El procesamiento comienza automáticamente después de la subida. Antes de reproducir la pista, espera hasta que esté lista — consulta GET /v1/track/{track_id} hasta que track.track_status_id sea ready, o configura un webhook (paso siguiente) para recibir notificaciones en lugar de hacer polling.

6. Opcional: Webhooks

Añade un webhook en Settings → Webhook para recibir notificaciones cuando una pista alcanza un resultado terminal (ready, incomplete, error o init_error) y cuando su conjunto completo de archivos está listo. Consulta la documentación del webhook Track Processing.

Imágenes de portada

ADN analiza automáticamente las pistas subidas en busca de arte de portada incrustado. También puedes subir una imagen de portada por separado vía la Covers API. Cuando hay una imagen, ADN extrae colores (disponibles como theme) que se pueden usar para estilizar la UI de tu player.