1
WebRTC Implementation
urko edited this page 2025-05-11 21:05:56 +01:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

1 Repository map & touch-points

What you have Where to extend / create
app/src/main/java/com/urkob/wittrail_android/CameraXRecordingService.kt (Wittrail Gitea) Extend: add an EncoderPipeline inner object and a WebRtcStreamer helper.
app/src/main/java/com/urkob/wittrail_android/MainActivity.kt (Wittrail Gitea) 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 gRPCWebRTC DTLS.
AndroidManifest.xml (root) (Wittrail Gitea) Add <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION"/> (API 34+) and declare the service type `<foregroundServiceType camera microphone dataSync>` (Android Developers)
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)

2 Client-side capture → encoder → WebRTC pipeline

2.1 Capture & encode on-device

// 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 youll 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.webrtcs MediaCodecVideoEncoder (GitHub). CameraXs VideoCapture already feeds a MediaCodec session internally (WebRTC), 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 RtpSenders (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 Googles 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 (25 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)
Camera + Audio CAMERA, RECORD_AUDIO (Android Developers) 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