StreamPack Android SDK

repository·main·Indexed 18 days ago

https://github.com/thibaultbee/streampack

A high-performance, modular Android SDK for low-latency live streaming supporting RTMP, RTMPS, and SRT protocols via Camera2 and MediaCodec APIs. It provides components for camera and screen recording streams, a minimalist MPEG-TS muxer (TSMuxer), and modular extensions for UI (XML and Jetpack Compose), background services, and various streaming protocols.

Tokens
9.9K
Snippets
25
Records
36
Agent score
62%

What's inside StreamPack

  1. Use the MPEG transport stream (TS) muxer

    main

    The TSMuxer is a minimalist MPEG-TS muxer designed to manage packet encapsulation and section tables (PAT, PMT, SDT). It allows you to manage multiple services and streams, and supports encoding AAC and H264 frames into the transport stream.

    Key capabilities include:

    • Adding and removing streams.
    • Adding and removing services.
    • Encoding AAC and H264 frames.
  2. Compare DualEndpoint vs DualStreamer

    main

    When deciding how to handle simultaneous streaming and recording, choose based on your hardware constraints and quality requirements:

    | Feature | DualEndpoint | DualStreamer | | :--- | :--- | : | | Encoder Strategy | Single encoder (1 video, 1 audio) | Multi-encoder (independent) | | Resource Usage | Low (Efficient) | High | | Flexibility | Same settings for both outputs | Different settings (bitrate, codec, etc.) per output | | Best Use Case | When hardware resources are limited | | Best Use Case | When you need high-quality recording separate from live stream settings |

  3. Understand Streamer types and use cases

    main

    A Streamer is the primary class used to stream audio and video from a source to an endpoint. It manages audio/video sources, encoders, and the endpoint. Depending on your requirements for independent outputs, you should choose one of the following types:

    • SingleStreamer: Use this for a single output (e.g., streaming live OR recording to a file).
    • DualStreamer: Use this for exactly two independent outputs (e.g., streaming live AND recording to a file simultaneously).
    • StreamerPipeline: Use this for complex scenarios requiring multiple independent outputs (e.g., saving audio to one file and video to another file).
  4. Handle Device Rotation with RotationProviders

    main

    To ensure the stream orientation matches the device, use a RotationProvider. StreamPack provides two built-in implementations:

    • SensorRotationProvider: Uses OrientationEventListener to follow physical device orientation.
    • DisplayRotationProvider: Uses DisplayManager and returns the last known orientation if the display is locked.

    Usage via Listener

    val rotationProvider = SensorRotationProvider(context)
    rotationProvider.addListener(object : IRotationProvider.Listener {
        override fun onOrientationChanged(rotation: Int) {
            streamer.setTargetRotation(rotation)
        }
    })

    Usage via Coroutines (Flow)

    Transform a provider into a Flow using asFlowProvider():

    val rotationFlowProvider = rotationProvider.asFlowProvider()
    rotationFlowProvider.rotationFlow.collect { rotation ->
        streamer.setTargetRotation(rotation)
    }
  5. Use SingleStreamer implementations

    main

    The SingleStreamer is a specialized Streamer that targets a single output. Several pre-defined implementations and factories are available:

    • AudioOnlySingleStreamer: Streams only from an audio source (defaults to microphone).
    • VideoOnlySingleStreamer: Streams only from a video source (defaults to microphone).
    • cameraSingleStreamer: A factory to create a streamer using a camera source.
    • videoMediaProjectionSingleStreamer: A factory for media projection video sources (requires setting activity result).
    • audioVideoMediaProjectionSingleStreamer: A factory for media projection video and audio sources (requires setting activity result).

    By default, these use a DynamicEndpoint, which automatically infers the protocol from the MediaDescriptor provided during open or startStream calls.

  6. What are StreamPack extensions

    main
    StreamPack extensions are modular components that depend on external libraries to provide additional functionality to the core SDK. They allow you to add specific capabilities (such as specialized streaming protocols or hardware integrations) without bloating the core library.
  7. How Streamers work: Single, Dual, and Pipeline

    main

    A Streamer represents a complete streaming pipeline from capture to endpoint (encoding, muxing, and sending). StreamPack provides different types based on your output requirements:

    • SingleStreamer: Best for a single output (e.g., just live streaming or just recording).
    • DualStreamer: Provides two independent outputs (e.g., independent live stream and independent local recording).
    • StreamerPipeline: For complex scenarios requiring multiple independent outputs (e.g., sending video to a server while saving audio to a separate file).

    Streamers can be instantiated via factories (like cameraSingleStreamer) or manually by setting setAudioSource and setVideoSource using SourceFactory implementations.

  8. Live stream and record simultaneously using DualStreamer

    main

    For scenarios where you need different settings (such as different codecs or bitrates) for your live stream and your recording, use a DualStreamer.

    Unlike DualEndpoint, which uses a single encoder for both outputs, DualStreamer manages two independent outputs. This provides maximum flexibility at the cost of higher hardware resource consumption because it uses multiple encoders.

    val streamer = DualStreamer(context)
    
    // To start the live stream on the first output
    streamer.first.startStream("rtmp://serverip:1935/s/streamKey")
    // To start the recording on the second output
    streamer.second.startStream("file:///path.to.file.mp4")
  9. Quick start with TSMuxer

    main

    To use the TSMuxer, follow these three steps:

    1. Instantiate the muxer: Provide an IMuxerListerner to handle the output packets.
    2. Register services and streams: Use addStreams to register service information and audio/video configurations. This returns a map where you can retrieve the streamPid using your configuration object as a key.
    3. Encode frames: Pass encoded frames and their corresponding streamPid to the encode method.
    // 1. Instantiate
    val muxer = TSMuxer(listener = object : IMuxerListerner {
        override fun onOutputFrame(packet: Packet) {
            // Use packet
        }
    })
    
    // 2. Register services and streams
    val streamPid = muxer.addStreams(serviceInfo, listOf(audioConfig))[audioConfig]
    
    // 3. Encode frames
    muxer.encode(frame, streamPid)
  10. Live stream and record simultaneously using DualEndpoint

    main

    Starting from version 3.0.0, you can perform live streaming and recording at the same time using a DualEndpoint. This approach uses a single encoder (one for video and one for audio) and pushes the encoded frames to two different endpoints. This is the most resource-efficient method as it minimizes hardware usage.

    To implement this, use a DualEndpointFactory to define a mainEndpointFactory (typically for recording) and a secondEndpointFactory (typically for live streaming). Note that if you use SrtEndpointFactory, the SRT package must be included in your project.

    Workflow:

    1. Initialize the DualEndpointFactory.
    2. Create a SingleStreamer with that factory.
    3. Open the main endpoint via streamer.open(url).
    4. Cast the streamer's endpoint to DualEndpoint and call openSecond(url).
    5. Call streamer.startStream() to start the main endpoint.
    6. Call endpoint.startStreamSecond() to start the second endpoint.
    val dualEndpointFactory = DualEndpointFactory(
        mainEndpointFactory = MediaMuxerEndpointFactory(),
        secondEndpointFactory = SrtEndpointFactory() // SRT package is required for SrtEndpointFactory
    )
    
    val streamer = SingleStreamer(
        context,
        endpointFactory = dualEndpointFactory
    )
    
    // Implementation steps:
    streamer.open("rtmp/serverip:1935/s/streamKey") // open the main endpoint
    val endpoint = streamer.endpoint as DualEndpoint
    endpoint.openSecond("file:///path.to.file.mp4") // open the second endpoint
    streamer.startStream() // start the streamer and the first endpoint
    endpoint.startStreamSecond() // start the second endpoint
  11. Install StreamPack dependencies

    main

    StreamPack is modular. You must include streampack-core and then add the specific modules required for your project (UI, protocols, or services).

    Available modules:

    • streampack-core: The base library.
    • streampack-ui: For XML-based UI, including PreviewView.
    • streampack-compose: For Jetpack Compose UI, including SourcePreview.
    • streampack-services: For background services, including screen capture and media projection services.
    • streampack-rtmp: Support for RTMP and RTMPS protocols.
    • streampack-srt: Support for SRT protocol.
    dependencies {
        implementation 'io.github.thibaultbee.streampack:streampack-core:3.2.0'
        // For xml UI (incl. PreviewView)
        implementation 'io.github.thibaultbee.streampack:streampack-ui:3.2.0'
        // Or compose UI (incl. SourcePreview)
        implementation 'io.github.thibaultbee.streampack:streampack-compose:3.2.0'
        // For services (incl. screen capture/media projection service)
        implementation 'io.github.thibaultbee.streampack:streampack-services:3.2.0'
        // For RTMP
        implementation 'io.github.thibaultbee.streampack:streampack-rtmp:3.2.0'
        // For SRT
        implementation 'io.github.thibaultbee.streampack:streampack-srt:3.2.0'
    }