Skip to content

Commit 973542c

Browse files
committed
feat(*): initial version of AMF, FLV and RTMP
1 parent fa9b9bc commit 973542c

File tree

206 files changed

+17052
-2
lines changed

Some content is hidden

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

206 files changed

+17052
-2
lines changed

.github/dependabot.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# To get started with Dependabot version updates, you'll need to specify which
2+
# package ecosystems to update and where the package manifests are located.
3+
# Please see the documentation for all configuration options:
4+
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5+
6+
version: 2
7+
updates:
8+
- package-ecosystem: "gradle" # See documentation for possible values
9+
directory: "/" # Location of package manifests
10+
schedule:
11+
interval: "weekly"

.github/workflows/build.yml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
name: Assemble and Test
2+
3+
on:
4+
[ workflow_dispatch, push ]
5+
6+
jobs:
7+
build:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- uses: actions/checkout@v4
11+
- uses: actions/setup-java@v4
12+
with:
13+
java-version: '21'
14+
distribution: 'adopt'
15+
- name: Cache Gradle packages
16+
uses: actions/cache@v4
17+
with:
18+
path: ~/.gradle/caches
19+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
20+
restore-keys: ${{ runner.os }}-gradle
21+
- name: Make gradlew executable
22+
working-directory: .
23+
run: chmod +x ./gradlew
24+
- name: Assemble
25+
working-directory: .
26+
run: ./gradlew assemble --info --stacktrace
27+
test:
28+
needs: build
29+
runs-on: ubuntu-latest
30+
steps:
31+
- uses: actions/checkout@v4
32+
- uses: actions/setup-java@v4
33+
with:
34+
java-version: '21'
35+
distribution: 'adopt'
36+
- name: Cache Gradle packages
37+
uses: actions/cache@v4
38+
with:
39+
path: ~/.gradle/caches
40+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
41+
restore-keys: ${{ runner.os }}-gradle
42+
- name: Make gradlew executable
43+
working-directory: .
44+
run: chmod +x ./gradlew
45+
- name: Test
46+
working-directory: .
47+
run: ./gradlew allTest --info --stacktrace
48+
kover:
49+
needs: test
50+
runs-on: ubuntu-latest
51+
steps:
52+
- uses: actions/checkout@v4
53+
- uses: actions/setup-java@v4
54+
with:
55+
java-version: '21'
56+
distribution: 'adopt'
57+
- name: Cache Gradle packages
58+
uses: actions/cache@v4
59+
with:
60+
path: ~/.gradle/caches
61+
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
62+
restore-keys: ${{ runner.os }}-gradle
63+
- name: Make gradlew executable
64+
working-directory: .
65+
run: chmod +x ./gradlew
66+
- name: Kover report
67+
working-directory: .
68+
run: ./gradlew koverHtmlReport --info --stacktrace
69+
- name: Upload Kover report
70+
uses: actions/upload-artifact@v4
71+
with:
72+
name: kover-report.zip
73+
path: build/reports/kover/html
74+
- name: Kover verify
75+
working-directory: .
76+
run: ./gradlew koverVerify --info --stacktrace

.github/workflows/pull-request.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Measure coverage
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
report-coverage:
8+
runs-on: ubuntu-latest
9+
permissions:
10+
pull-requests: write
11+
steps:
12+
- uses: actions/checkout@v4
13+
- name: Set up JDK
14+
uses: actions/setup-java@v4
15+
with:
16+
java-version: '21'
17+
distribution: 'adopt'
18+
- name: Grant execute permission for gradlew
19+
run: chmod +x gradlew
20+
- name: Generate kover coverage report
21+
run: ./gradlew koverXmlReport
22+
- name: Add coverage report to PR
23+
id: kover
24+
uses: mi-kas/kover-report@v1
25+
with:
26+
path: |
27+
${{ github.workspace }}/build/reports/kover/report.xml
28+
title: Code Coverage
29+
update-comment: true
30+
min-coverage-overall: 80
31+
min-coverage-changed-files: 80
32+
coverage-counter-type: LINE

.github/workflows/release.yml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: Publish package to Maven Central
2+
3+
on:
4+
release:
5+
types: [ published ]
6+
7+
jobs:
8+
release:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- uses: actions/checkout@v4
12+
- uses: actions/setup-java@v4
13+
with:
14+
java-version: '21'
15+
distribution: 'adopt'
16+
- name: Make gradlew executable
17+
run: chmod +x ./gradlew
18+
- name: Publish to Maven Central
19+
run: ./gradlew publishAllPublicationsToMavenCentral --no-configuration-cache
20+
env:
21+
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.SIGNING_IN_MEMORY_KEY }}
22+
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.SIGNING_KEY_ID }}
23+
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.SIGNING_PASSWORD }}
24+
ORG_GRADLE_PROJECT_centralPortalUsername: ${{ secrets.CENTRAL_PORTAL_USERNAME }}
25+
ORG_GRADLE_PROJECT_centralPortalPassword: ${{ secrets.CENTRAL_PORTAL_PASSWORD }}
26+
- name: Generate documentation
27+
run: ./gradlew dokkaHtmlMultiModule
28+
- name: Deploy API documentation to Github Pages
29+
uses: JamesIves/github-pages-deploy-action@v4
30+
with:
31+
github_token: ${{ secrets.GITHUB_TOKEN }}
32+
branch: gh-pages
33+
folder: build/dokkaCustomMultiModuleOutput

.gitignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
*.iml
2+
.gradle
3+
.idea
4+
.DS_Store
5+
build
6+
captures
7+
.externalNativeBuild
8+
.cxx
9+
.kotlin
10+
local.properties
11+
xcuserdata

README.md

Lines changed: 202 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,202 @@
1-
# krtmp
2-
RTMP/FLV/AMF for Kotlin Multiplatform
1+
# krtmp: A RTMP, FLV and AMF library for Kotlin Multiplatform and Android
2+
3+
krtmp is a Kotlin Multiplatform implementation of RTMP, FLV and AMF protocols from legacy RTMP to
4+
enhanced RTMP v2.
5+
6+
# RTMP
7+
8+
A RTMP client and server library for Kotlin Multiplatform.
9+
10+
Features:
11+
12+
- [x] RTMP client
13+
- [x] RTMP server
14+
- [ ] Statistics
15+
- [x] Support for legacy RTMP
16+
- [x] Support for enhanced RTMP v2: Reconnect
17+
18+
Supported protocols:
19+
20+
- [x] RTMP
21+
- [x] RTMPS
22+
- [x] RTMPT (not tested)
23+
24+
## Installation
25+
26+
Adds the following dependency to your project:
27+
28+
```kotlin
29+
implementation("io.github.thibaultbee.krtmp:rtmp:0.9.0")
30+
```
31+
32+
## Usage
33+
34+
### Client
35+
36+
Creates a RTMP client with the Factory `RtmpClient`:
37+
38+
```kotlin
39+
val client = RtmpClient(
40+
"rtmp://my.server.com/app/streamkey" // Your RTMP server URL (incl app name and stream key)
41+
)
42+
```
43+
44+
Then prepare your live by sending these messages to the server:
45+
46+
```kotlin
47+
client.connect()
48+
client.createStream()
49+
client.publish(StreamPublishType.LIVE)
50+
```
51+
52+
If you already have FLV data, write your video/audio data:
53+
54+
```kotlin
55+
try {
56+
// Write metadata
57+
val metadata = OnMetadata.Metadata(...)
58+
client.writeSetDataFrame(metadata)
59+
60+
while (true) {
61+
// Write audio data. `audioData` are in `AudioTagHeader` format. See FLV specification for more details.
62+
client.writeAudio(audioTimestamp, audioData)
63+
// Write video data. `videoData` are in `VideoTagHeader` format. See FLV specification for more details.
64+
client.writeVideo(videoTimestamp, videoData)
65+
}
66+
} catch (e: Exception) {
67+
// Handle exception
68+
}
69+
```
70+
71+
See [FLV](#flv) for more details to write audio and video frames..
72+
73+
### Server
74+
75+
Use the `RtmpServer` to create a RTMP server:
76+
77+
```kotlin
78+
val server = RtmpServer("0.0.0.0:1935") // Listening on port 1935
79+
```
80+
81+
Then start the server:
82+
83+
```kotlin
84+
server.listen()
85+
```
86+
87+
# FLV
88+
89+
A muxer/demuxer for FLV.
90+
91+
Features:
92+
93+
- [x] Muxer for FLV
94+
- [x] Demuxer for FLV
95+
- [x] AMF0 metadata
96+
- [ ] AMF3 metadata
97+
- [x] Support for legacy RTMP
98+
- [x] Support for enhanced RTMP v1: AV1, HEVC, VP8, VP9
99+
- [x] Support for enhanced RTMP v2: Multitrack, Opus,...
100+
101+
## Installation
102+
103+
Adds the following dependencies to your project:
104+
105+
```kotlin
106+
implementation("io.github.thibaultbee.krtmp:flv:0.9.0")
107+
```
108+
109+
## Usage
110+
111+
Creates a FLV muxer and add audio/video data:
112+
113+
```kotlin
114+
val muxer = FLVMuxer(path = "/path/to/file.flv")
115+
116+
// Write FLV header
117+
flvMuxer.encodeFlvHeader(hasAudio, hasVideo)
118+
119+
// Register audio configurations (if any)
120+
val audioConfig = FLVAudioConfig(
121+
FlvAudioConfig.SoundFormat.AAC,
122+
FlvAudioConfig.SoundRate.KHZ44,
123+
FlvAudioConfig.SoundSize.SND8BIT,
124+
FlvAudioConfig.SoundType.STEREO
125+
)
126+
// Register video configurations (if any)
127+
val videoConfig = FLVVideoConfig(
128+
)
129+
130+
// Write onMetadata
131+
muxer.encode(0, OnMetadata(audioConfig, videoConfig))
132+
133+
// Write audio/video data
134+
muxer.encode(audioFrame)
135+
muxer.encode(videoFrame)
136+
muxer.encode(audioFrame)
137+
muxer.encode(videoFrame)
138+
139+
// Till you're done, then
140+
muxer.flush()
141+
142+
// Close the output
143+
muxer.close()
144+
```
145+
146+
# AMF
147+
148+
A serializer/deserializer for AMF0 and AMF3.
149+
150+
Features:
151+
152+
- [x] Serializer for AMF0
153+
- [ ] Serializer for AMF3
154+
- [x] Deserializer for AMF0
155+
- [ ] Deserializer for AMF3
156+
157+
## Installation
158+
159+
It requires `kotlinx.serialization` library.
160+
See [Setup](https://github.com/Kotlin/kotlinx.serialization?tab=readme-ov-file#setup) for more
161+
details.
162+
Then, adds the following dependencies to your project:
163+
164+
```kotlin
165+
implementation("io.github.thibaultbee.krtmp:amf:0.9.0")
166+
```
167+
168+
## Usage
169+
170+
Creates a class and make it serializable with `@Serializable` annotation:
171+
172+
```kotlin
173+
@Serializable
174+
class MyData(val a: Int, val b: String)
175+
```
176+
177+
Then you can serialize it to AMF0:
178+
179+
```kotlin
180+
val data = MyData(1, "Hello")
181+
val array = Amf.encodeToByteArray(MyData.serializer(), data)
182+
```
183+
184+
# TODO
185+
186+
- [ ] More tests (missing tests samples)
187+
188+
# Licence
189+
190+
Copyright 2023 Thibault B.
191+
192+
Licensed under the Apache License, Version 2.0 (the "License");
193+
you may not use this file except in compliance with the License.
194+
You may obtain a copy of the License at
195+
196+
http://www.apache.org/licenses/LICENSE-2.0
197+
198+
Unless required by applicable law or agreed to in writing, software
199+
distributed under the License is distributed on an "AS IS" BASIS,
200+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201+
See the License for the specific language governing permissions and
202+
limitations under the License.

0 commit comments

Comments
 (0)