commit dc82d318ce29a9a57d417fede8f5d19c00e02d95 Author: urko Date: Sun May 11 21:05:56 2025 +0100 Add WebRTC Implementation diff --git a/WebRTC-Implementation.md b/WebRTC-Implementation.md new file mode 100644 index 0000000..106bcaf --- /dev/null +++ b/WebRTC-Implementation.md @@ -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** `` (API 34+) and declare the service type \`\\` ([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(replay = 0) + val audio = MutableSharedFlow(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"