Add WebRTC Implementation
commit
dc82d318ce
105
WebRTC-Implementation.md
Normal file
105
WebRTC-Implementation.md
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
## 1 Repository map & touch-points
|
||||||
|
|
||||||
|
| What you have | Where to extend / create | | |
|
||||||
|
| ----------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- | ------------------------------------- |
|
||||||
|
| `app/src/main/java/com/urkob/wittrail_android/CameraXRecordingService.kt` ([Wittrail Gitea][1]) | **Extend**: add an **EncoderPipeline** inner object and a **WebRtcStreamer** helper. | | |
|
||||||
|
| `app/src/main/java/com/urkob/wittrail_android/MainActivity.kt` ([Wittrail Gitea][1]) | **Minor**: request the new foreground-service types at runtime (API 34). | | |
|
||||||
|
| *no* `data/` layer yet | **Add** a `repository` package that holds an `UploadRepository` to push encrypted chunks via gRPC–WebRTC DTLS. | | |
|
||||||
|
| `AndroidManifest.xml` (root) ([Wittrail Gitea][2]) | **Add** `<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"/>` (API 34+) and declare the service type \`\<foregroundServiceType camera | microphone | dataSync>\` ([Android Developers][3]) |
|
||||||
|
| `build.gradle` (app) | **Add** `implementation("org.webrtc:google-webrtc:1.0.32006")`, `implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.8.1")` and the CameraX BOM (`androidx.camera:camera-bom:1.3.0`) ([WebRTC][4]) | | |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2 Client-side capture → encoder → WebRTC pipeline
|
||||||
|
|
||||||
|
### 2.1 Capture & encode on-device
|
||||||
|
|
||||||
|
```kotlin
|
||||||
|
// inside CameraXRecordingService.kt (new)
|
||||||
|
private val encoderPipeline by lazy {
|
||||||
|
val video = MutableSharedFlow<EncodedVideoChunk>(replay = 0)
|
||||||
|
val audio = MutableSharedFlow<EncodedAudioChunk>(replay = 0)
|
||||||
|
|
||||||
|
// Register camera surface
|
||||||
|
VideoCapture.withOutput(MediaStoreOutputOptions.Builder(...).build())
|
||||||
|
.also { it.setVideoEncoder(VideoEncoderConfig.H264(2_000_000)) } // ≈2 Mbps
|
||||||
|
.also { it.setAudioEncoder(AudioEncoderConfig.AAC(128_000)) }
|
||||||
|
.registerPipeline(video, audio) // <-- extension function you’ll add
|
||||||
|
|
||||||
|
EncoderPipeline(video, audio) // data-class you create
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
*Why H-264 + AAC?* They are hardware-accelerated on every device since API 21 ✔️ and directly understood by `org.webrtc`’s `MediaCodecVideoEncoder` ([GitHub][5]).
|
||||||
|
CameraX’s *VideoCapture* already feeds a `MediaCodec` session internally ([WebRTC][4]), so you only tap its encoded output instead of raw YUV/PCM.
|
||||||
|
|
||||||
|
### 2.2 Secure streaming with WebRTC `PeerConnection`
|
||||||
|
|
||||||
|
1. **Create** `WebRtcStreamer.kt` that owns a single `PeerConnection` + two `RtpSender`s (audio/video).
|
||||||
|
2. Call `webRtcStreamer.sendVideo(chunk)` each time `encoderPipeline.video.emit(chunk)` fires.
|
||||||
|
3. Negotiate DTLS-SRTP with the server; the signalling channel can be a lightweight REST call to your back-end (later replaceable by gRPC bidirectional).
|
||||||
|
4. Enable **SFrame** end-to-end media encryption if you need payload privacy; the hash for the *timestamp* is calculated server-side after DTLS decryption.
|
||||||
|
|
||||||
|
A bare-bones set-up (no ICE-servers, only TURN) is under 50 lines – see Google’s minimal Kotlin sample .
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3 Server-side hash + qualified time-stamp
|
||||||
|
|
||||||
|
* Deploy a tiny Go service that
|
||||||
|
|
||||||
|
1. Receives SRTP packets from `webrtc::TrackLocalStaticRtp`;
|
||||||
|
2. Re-orders & re-assembles them into MP4 fragments every **N seconds** (2–5 s gives smooth playback);
|
||||||
|
3. Calculates a SHA-256 digest for each fragment and calls the **Camerfirma Q-TSA** REST endpoint (`/timestamp`) – they follow ETSI EN 319-421 / 422 .
|
||||||
|
* Store `{hash, RFC3161_tsToken, fragmentURI}` in Postgres. Because the time-stamps are *qualified*, Art. 41.2 eIDAS les da “valor probatorio equivalente al de una firma notarial” in la UE.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4 Permissions & API-level quirks
|
||||||
|
|
||||||
|
| Feature | API ≤ 33 | API 34+ (Android 14) |
|
||||||
|
| ------------------ | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| Foreground-service | `android.permission.FOREGROUND_SERVICE` | MUST also declare *type* in manifest **and** request `FOREGROUND_SERVICE_MEDIA_PROJECTION` at runtime ([Android Developers][3]) |
|
||||||
|
| Camera + Audio | `CAMERA`, `RECORD_AUDIO` ([Android Developers][6]) | Igual, pero si target 34, the Privacy Sandbox dialog is automatic. |
|
||||||
|
| External write | Scoped-storage; use `MediaStore` (already in your code) | Same; WRITE\_EXTERNAL\_STORAGE not needed ≥ API 30. |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5 Examples of *good* Issues for non-devs (compliance stream)
|
||||||
|
|
||||||
|
| Title | Description (plain language) | Labels | Milestone |
|
||||||
|
| ------------------------------------------------ | --------------------------------------------------------------------------------------------- | -------------------------- | ------------------ |
|
||||||
|
| “Review ETSI 319-421 compliance gap” | “Read the norm, tick each MUST & SHOULD in an excel, flag red items.” | `legal`, `doc`, `research` | `✍ ETSI analysis` |
|
||||||
|
| “Choose EU funding window” | “Compare Digital Europe vs Horizon Europe: eligibility, calendar, TRL. Write 1-page summary.” | `funding`, `planning` | `💶 Grant Scan Q3` |
|
||||||
|
| “Draft DPIA (Data Protection Impact Assessment)” | “Fill the AEPD template for the pilot.” | `privacy`, `regulation` | `📜 Trust Ops MVP` |
|
||||||
|
|
||||||
|
Your UX guide on how to create them—complete with screenshots—already lives in **docs/onboarding/issues\_guide.md**; link to that in every new employee e-mail.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6 Pros / contras of this architecture
|
||||||
|
|
||||||
|
| Aspect | Pros | Contras / Mitigation |
|
||||||
|
| -------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------- |
|
||||||
|
| **CameraX + MediaCodec** | HW-accelerated, low battery, single API | Needs targetSdk 33+; some Samsung A-series ships buggy encoder → keep `device-quirks` table. |
|
||||||
|
| **WebRTC SRTP path** | No open port on device; NAT traversal built-in | TURN fees if many users → deploy coturn on cheap edge VMs. |
|
||||||
|
| **Qualified TSA** | Probative value by default (Art. 41 eIDAS) | Each token ≈ €0.05 at volume → batch 5 s fragments. |
|
||||||
|
| **Hash first, TSA second** | Small payload; privacy (only digest leaves device) | Requires buffering until TSA response (<300 ms). |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Next steps
|
||||||
|
|
||||||
|
1. **Add the new permissions** to `AndroidManifest.xml`.
|
||||||
|
2. Drop the code snippets above and run on API 33 for smoke-test.
|
||||||
|
3. Spin up `pion/webrtc` demo server (one-liner) and verify you see live video.
|
||||||
|
4. Swap in Camerfirma sandbox credentials and log the RFC-3161 token.
|
||||||
|
|
||||||
|
Once that works end-to-end, you can harden (device attestation, FIDO key-sealed AES, etc.) and then move to the larger roadmap we drafted earlier
|
||||||
|
|
||||||
|
[1]: https://gitea.urkob.com/wittrail/client-android/src/branch/master/app/src/main/java/com/urkob/wittrail_android "client-android/wittrail_android at master - client-android - Wittrail Gitea"
|
||||||
|
[2]: https://gitea.urkob.com/wittrail/client-android/src/branch/master/app "client-android/app at master - client-android - Wittrail Gitea"
|
||||||
|
[3]: https://developer.android.com/develop/background-work/services/fgs/declare?utm_source=chatgpt.com "Declare foreground services and request permissions"
|
||||||
|
[4]: https://issues.webrtc.org/issues/40644339?utm_source=chatgpt.com "Large amounts of CPU time spent in Thread::ClearInternal when ..."
|
||||||
|
[5]: https://github.com/developerspace-samples/WebRTC-Kotlin-Sample?utm_source=chatgpt.com "developerspace-samples/WebRTC-Kotlin-Sample - GitHub"
|
||||||
|
[6]: https://developer.android.com/media/camera/camera-deprecated/camera-api?utm_source=chatgpt.com "Camera API | Android media - Android Developers"
|
Loading…
x
Reference in New Issue
Block a user