
Open/close Widevine sessions, build/verify SignedMessage license requests/responses from PSSH, parse/convert PSSH boxes, extract and decrypt content keys, with protobuf models and multiplatform-safe crypto.
Kotlin Multiplatform library that mirrors the core functionality of pywidevine: open/close Widevine sessions, build signed license requests from PSSH, verify and parse license responses, and expose decrypted content keys.
Built on the same protobuf models as pywidevine and designed to run on JVM and Android targets.
See also: API docs in docs/API.md
Gradle (Kotlin DSL):
dependencies {
implementation("io.github.samfun75:ktvine:0.0.3")
}This is a Kotlin Multiplatform library. The artifact publishes for JVM and Android. iOS/Linux targets may be added later.
The typical flow is the same as pywidevine, adapted to Kotlin:
import org.samfun.ktvine.core.Device
import org.samfun.ktvine.cdm.Cdm
val device = Device.loads(base64Wvd) // or Device.loads(bytes)
val cdm = Cdm.fromDevice(device)val sessionId = cdm.open()
// Optional: service cert as raw SignedDrmCertificate bytes or SignedMessage-wrapped bytes
// cdm.setServiceCertificate(sessionId, serviceCertBytes)import org.samfun.ktvine.core.PSSH
val pssh = PSSH(psshBase64) // or PSSH(psshBytes)
val challenge = cdm.getLicenseChallenge(
sessionId = sessionId,
pssh = pssh
)
// Send `challenge` bytes to your Widevine license server (not provided by this library)// licenseMessage: SignedMessage(LICENSE) payload from your server (raw bytes)
cdm.parseLicense(sessionId, licenseMessage)
val keys = cdm.getKeys(sessionId) // List<Key>
keys.forEach { println(it) }
cdm.close(sessionId)PSSH parsing and conversion helpers are included:
PSSH(psshBase64), PSSH(psshBytes)
pssh.keyIds() → List
pssh.dump() (bytes), pssh.dumps() (Base64)pssh.toWidevine()pssh.toPlayready(laUrl, luiUrl, dsId, decryptorSetup, customData) (builds v4.3.0.0 header)PSSH.new(systemId, keyIds = ..., initData = ..., version = 0/1)
pssh.setKeyIds(listOf(uuid1, uuid2))
Public methods throw typed exceptions you can catch:
suspend fun main() {
val device = Device.loads(System.getenv("WVD_BASE64"))
val cdm = Cdm.fromDevice(device)
val session = cdm.open()
val pssh = PSSH(System.getenv("PSSH_BASE64"))
val challenge = cdm.getLicenseChallenge(session, pssh)
val licenseMessage: ByteArray = postToYourServer(challenge) // implement yourself
cdm.parseLicense(session, licenseMessage)
cdm.getKeys(session).forEach { println(it) }
cdm.close(session)
}KDoc is provided throughout the codebase; you can also read a compact overview in docs/API.md.
See LICENSE.
Kotlin Multiplatform library that mirrors the core functionality of pywidevine: open/close Widevine sessions, build signed license requests from PSSH, verify and parse license responses, and expose decrypted content keys.
Built on the same protobuf models as pywidevine and designed to run on JVM and Android targets.
See also: API docs in docs/API.md
Gradle (Kotlin DSL):
dependencies {
implementation("io.github.samfun75:ktvine:0.0.3")
}This is a Kotlin Multiplatform library. The artifact publishes for JVM and Android. iOS/Linux targets may be added later.
The typical flow is the same as pywidevine, adapted to Kotlin:
import org.samfun.ktvine.core.Device
import org.samfun.ktvine.cdm.Cdm
val device = Device.loads(base64Wvd) // or Device.loads(bytes)
val cdm = Cdm.fromDevice(device)val sessionId = cdm.open()
// Optional: service cert as raw SignedDrmCertificate bytes or SignedMessage-wrapped bytes
// cdm.setServiceCertificate(sessionId, serviceCertBytes)import org.samfun.ktvine.core.PSSH
val pssh = PSSH(psshBase64) // or PSSH(psshBytes)
val challenge = cdm.getLicenseChallenge(
sessionId = sessionId,
pssh = pssh
)
// Send `challenge` bytes to your Widevine license server (not provided by this library)// licenseMessage: SignedMessage(LICENSE) payload from your server (raw bytes)
cdm.parseLicense(sessionId, licenseMessage)
val keys = cdm.getKeys(sessionId) // List<Key>
keys.forEach { println(it) }
cdm.close(sessionId)PSSH parsing and conversion helpers are included:
PSSH(psshBase64), PSSH(psshBytes)
pssh.keyIds() → List
pssh.dump() (bytes), pssh.dumps() (Base64)pssh.toWidevine()pssh.toPlayready(laUrl, luiUrl, dsId, decryptorSetup, customData) (builds v4.3.0.0 header)PSSH.new(systemId, keyIds = ..., initData = ..., version = 0/1)
pssh.setKeyIds(listOf(uuid1, uuid2))
Public methods throw typed exceptions you can catch:
suspend fun main() {
val device = Device.loads(System.getenv("WVD_BASE64"))
val cdm = Cdm.fromDevice(device)
val session = cdm.open()
val pssh = PSSH(System.getenv("PSSH_BASE64"))
val challenge = cdm.getLicenseChallenge(session, pssh)
val licenseMessage: ByteArray = postToYourServer(challenge) // implement yourself
cdm.parseLicense(session, licenseMessage)
cdm.getKeys(session).forEach { println(it) }
cdm.close(session)
}KDoc is provided throughout the codebase; you can also read a compact overview in docs/API.md.
See LICENSE.