Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates

version: 2
updates:
- package-ecosystem: "gradle" # See documentation for possible values
directory: "/" # Location of package manifests
schedule:
interval: "weekly"
76 changes: 76 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
name: Assemble and Test

on:
[ workflow_dispatch, push ]

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'adopt'
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Make gradlew executable
working-directory: .
run: chmod +x ./gradlew
- name: Assemble
working-directory: .
run: ./gradlew assemble --info --stacktrace
test:
needs: build
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'adopt'
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Make gradlew executable
working-directory: .
run: chmod +x ./gradlew
- name: Test
working-directory: .
run: ./gradlew allTest --info --stacktrace
kover:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'adopt'
- name: Cache Gradle packages
uses: actions/cache@v4
with:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- name: Make gradlew executable
working-directory: .
run: chmod +x ./gradlew
- name: Kover report
working-directory: .
run: ./gradlew koverHtmlReport --info --stacktrace
- name: Upload Kover report
uses: actions/upload-artifact@v4
with:
name: kover-report.zip
path: build/reports/kover/html
- name: Kover verify
working-directory: .
run: ./gradlew koverVerify --info --stacktrace
27 changes: 27 additions & 0 deletions .github/workflows/documentation.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Build and publish documentation

on:
workflow_dispatch:
release:
types: [ published ]

jobs:
update-api-documentation:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Java
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Generate API documentation
run: ./gradlew dokkaHtmlMultiModule
- name: Deploy API documentation to Github Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BRANCH: gh-pages
FOLDER: build/dokka/htmlMultiModule
32 changes: 32 additions & 0 deletions .github/workflows/pull-request.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
name: Measure coverage

on:
pull_request:

jobs:
report-coverage:
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- uses: actions/checkout@v4
- name: Set up JDK
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'adopt'
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Generate kover coverage report
run: ./gradlew koverXmlReport
- name: Add coverage report to PR
id: kover
uses: mi-kas/kover-report@v1
with:
path: |
${{ github.workspace }}/build/reports/kover/report.xml
title: Code Coverage
update-comment: true
min-coverage-overall: 80
min-coverage-changed-files: 80
coverage-counter-type: LINE
33 changes: 33 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
name: Publish package to Maven Central

on:
release:
types: [ published ]

jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'adopt'
- name: Make gradlew executable
run: chmod +x ./gradlew
- name: Publish to Maven Central
run: ./gradlew publishAllPublicationsToMavenCentral --no-configuration-cache
env:
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_IN_MEMORY_KEY }}
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }}
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.OSSRH_USERNAME }}
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.OSSRH_TOKEN }}
- name: Generate documentation
run: ./gradlew dokkaHtmlMultiModule
- name: Deploy API documentation to Github Pages
uses: JamesIves/github-pages-deploy-action@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
branch: gh-pages
folder: build/dokkaCustomMultiModuleOutput
11 changes: 11 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
*.iml
.gradle
.idea
.DS_Store
build
captures
.externalNativeBuild
.cxx
.kotlin
local.properties
xcuserdata
193 changes: 191 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,191 @@
# krtmp
RTMP/FLV/AMF for Kotlin Multiplatform
# krtmp: A RTMP/FLV/AMF library for Kotlin Multiplatform and Android

# RTMP

A RTMP client and server (soon) library for Kotlin Multiplatform.

Features:

- [x] RTMP publish client
- [ ] RTMP play client
- [ ] RTMP play2 client
- [ ] RTMP server
- [ ] Statistics

Supported protocols:

- [x] RTMP
- [x] RTMPS
- [x] RTMPT (partially)

## Installation

Adds the following dependency to your project:

```kotlin
implementation("io.github.thibaultbee.krtmp:rtmp:1.0.0")
```

## Usage

Creates a RTMP publish client with the Factory `RtmpClientConnectionFactory`:

```kotlin
val client = RtmpPublishClientConnectionFactory().create(
"rtmp://my.server.com/app/streamkey" // Your RTMP server URL (incl app name and stream key)
)
```

Then prepare your live by sending these messages to the server:

```kotlin
client.connect()
client.createStream()
client.publish(Command.Publish.Type.LIVE)
```

If you have raw audio and video frames, you need to mux them into FLV tag headers. You can use
the `FlvMuxer` class for that.

```kotlin
val flvMuxer = client.flvMuxer
```

See [FLV](#flv) for more details to write audio and video frames..

If you already have FLV data, write your video/audio data:

```kotlin
try {
// Write metadata
val metadata = OnMetadata.Metadata(...)
client.writeSetDataFrame(metadata)

while (true) {
// Write audio data. `audioData` are in `AudioTagHeader` format. See FLV specification for more details.
client.writeAudio(audioTimestamp, audioData)
// Write video data. `videoData` are in `VideoTagHeader` format. See FLV specification for more details.
client.writeVideo(videoTimestamp, videoData)
}
} catch (e: Exception) {
// Handle exception
}
```

For advanced configuration, see `RtmpClientSettings`.

# FLV

A muxer/demuxer for FLV.

Features:

- [x] Muxer for FLV
- [x] Demuxer for FLV
- [x] AMF0 metadata
- [ ] AMF3 metadata
- [x] Supported audio codec: AAC
- [x] Supported video codec: AVC/H.264 and enhanced RTMP codecs: HEVC/H.265, VP9, AV1

## Installation

Adds the following dependencies to your project:

```kotlin
implementation("io.github.thibaultbee.krtmp:flv:1.0.0")
```

## Usage

Creates a FLV muxer and add audio/video data:

```kotlin
val muxer = FlvMuxer()

// Register audio configurations (if any)
val audioConfig = FlvAudioConfig(
FlvAudioConfig.SoundFormat.AAC,
FlvAudioConfig.SoundRate.KHZ44,
FlvAudioConfig.SoundSize.SND8BIT,
FlvAudioConfig.SoundType.STEREO
)
val audioId = muxer.addStream(audioConfig)

// Register audio configurations (if any)
val videoConfig = FlvVideoConfig(

)
val videoId = muxer.addStream(videoConfig)

// Start the muxer (write FlvTag (if needed) and onMetaData)
muxer.startStream()

// Write audio/video data
muxer.write(audioFrame)
muxer.write(videoFrame)
muxer.write(audioFrame)
muxer.write(videoFrame)
// till you're done

// Stop the muxer
muxer.stopStream()

```

# AMF

A serializer/deserializer for AMF0 and AMF3.

Features:

- [x] Serializer for AMF0
- [ ] Serializer for AMF3
- [ ] Deserializer for AMF0
- [ ] Deserializer for AMF3

## Installation

It requires `kotlinx.serialization` library.
See [Setup](https://github.com/Kotlin/kotlinx.serialization?tab=readme-ov-file#setup) for more
details.
Then, adds the following dependencies to your project:

```kotlin
implementation("io.github.thibaultbee.krtmp:amf:1.0.0")
```

## Usage

Creates a class and make it serializable with `@Serializable` annotation:

```kotlin
@Serializable
class MyData(val a: Int, val b: String)
```

Then you can serialize it to AMF0:

```kotlin
val data = MyData(1, "Hello")
val array = Amf.encodeToByteArray(MyData.serializer(), data)
```

# TODO

- [x] A FLV/RTMP parameter for supported level: (legacy, enhanced v1, enhanced v2,...)

# Licence

Copyright 2023 Thibault B.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
Loading
Loading