FVP Flutter Plugin

repository·master·Indexed 43 days ago

https://github.com/wang-bin/fvp

A high-performance replacement for the official video_player implementation in Flutter. Powered by the libmdk SDK, FVP supports hardware-accelerated decoding and optimal rendering across Windows, Linux, macOS, iOS, Android, and HarmonyOS. It provides VideoPlayerController extensions for features like snapshots and recording, as well as a Backend Player API for advanced media control.

Tokens
7K
Snippets
30
Records
40
Agent score
57%

What's inside FVP

  1. Customize iOS launch screen assets

    master

    To change the launch screen image for the iOS version of the application, you can use either of the following methods:

    1. Direct File Replacement: Replace the existing image files located in the example/ios/Runner/Assets.xcassets/LaunchImage.imageset/ directory with your own assets.
    2. Xcode Interface:
      • Open the iOS workspace using open ios/Runner.xcworkspace.
      • In the Xcode Project Navigator, navigate to Runner/Assets.xcassets.
      • Drag and drop your desired images into the asset catalog.
    open ios/Runner.xcworkspace
  2. Use the fvp_example project as a starting point

    master

    The fvp_example project serves as a demonstration of how to integrate and use the fvp plugin within a Flutter application. It is based on the official Flutter video_player example, modified to enable fvp capabilities.

    To use this as a template, note that main.dart includes specific lines to enable the fvp plugin, which are not present in the standard video_player package example.

    # Note: main.dart is modified from the official video_player example to enable the fvp plugin.
  3. Install and setup FVP

    master

    To use FVP as a replacement for the official video_player implementation, add it to your pubspec.yaml dependencies:

    flutter pub add fvp

    Note: Since Flutter 3.27, fvp must be a direct dependency in your app's pubspec.yaml.

    After adding the dependency, you must call fvp.registerWith() in your main() function or anywhere before creating a player to ensure FVP is used for all platforms (especially Windows and Linux where the official implementation is used by default).

  4. Enable hardware decoders on Embedded Linux

    master

    To enable hardware acceleration on embedded Linux devices, you must remove the bundled FFmpeg libraries so the system can use its own:

    1. Delete libffmpeg.so.* from your app bundle (copied from the libmdk SDK).
    2. Raspberry Pi: Install ffmpeg and system FFmpeg libraries with v4l2 acceleration.
    3. Rockchip: Build and install ffmpeg-rockchip.
      • Tip: If using an ARM Mali driver on a Linux 6.x kernel, you may need to set export GL_UBO=1 to avoid GL driver bugs.
  5. Upgrade FVP binary dependencies manually

    master

    To upgrade binary dependencies for new features or bug fixes, follow the platform-specific steps:

    macOS and iOS

    Run the following in your project directory:

    pod cache clean mdk
    find . -name Podfile.lock -delete
    rm -rf {mac,i}os/Pods

    Other Platforms

    Set the environment variable FVP_DEPS_LATEST=1 and rebuild. Alternatively, run flutter pub cache clean if installed from pub.dev.

    Using an Immutable SDK/Mirror

    To use a specific SDK version or mirror, set FVP_DEPS_URL and FVP_DEPS_SHA256. These can also be set as CMake cache variables.

    FVP_DEPS_URL=https://example.com/mdk-sdk/releases/vX.Y.Z \
    FVP_DEPS_SHA256="replace-with-64-character-sha256" \
    flutter build apk

    Note: When FVP_DEPS_SHA256 is provided, FVP_DEPS_LATEST is ignored.

  6. Enable Subtitles

    master

    FVP requires libass for subtitle support.

    • Windows, macOS, HarmonyOS, and Android: libass is added automatically. (To reduce size, you can remove ass.dll, libass.dylib, or libass.so from the mdk-sdk if subtitles are not needed).
    • iOS: You must manually download and add ass.framework to your Xcode project.
    • Linux: You must install libass manually via your system package manager.

    Fallback Fonts

    If the required subtitle font is missing (e.g., on Android), you can add a font to your pubspec.yaml assets or provide a URL via registerWith:

    fvp.registerWith(options: {
      'subtitleFontFile': 'https://example.com/subfont.ttf'
    });
  7. Concept: Video Aspect Ratio Constants

    master

    FVP provides constants to control how video content is scaled within the renderer viewport:

    • ignoreAspectRatio: Stretches video content to fill the entire viewport.
    • keepAspectRatio: Scales the video as large as possible while maintaining the aspect ratio (letterboxing/pillarboxing).
    • keepAspectRatioCrop: Scales the video to cover the entire viewport while maintaining aspect ratio (cropping edges).
    const double ignoreAspectRatio = 0.0;
    const double keepAspectRatio = 1.1920928955078125e-7;
    const double keepAspectRatioCrop = -1.1920928955078125e-7;
  8. Register FVP as the default VideoPlayer implementation

    master

    To use FVP instead of the official video_player implementation, you must call registerWith(). If you do not call this, the system will fall back to the previous (usually official) implementation.

    To enable automatic registration via Dart tooling, add dartPluginClass: VideoPlayerRegistrant to your pubspec.yaml file.

    import 'package:fvp/fvp.dart';
    
    // Manual registration
    registerWith(options: {
      'platforms': ['windows', 'linux', 'macos'],
      'video.decoders': ['BRAW:scale=1/4', 'auto'],
      'maxWidth': screenWidth,
      'maxHeight': screenHeight,
      'subtitleFontFile': 'assets/subfont.ttf',
    });
  9. Handle video playback errors

    master

    Errors typically occur during media loading. You can monitor them by adding a listener to your VideoPlayerController:

    _controller.addListener(() {
      if (_controller.value.hasError && !_controller.value.isCompleted) {
        // Handle error
      }
    });
    _controller.addListener(() {
      if (_controller.value.hasError && !_controller.value.isCompleted) {
        ...
      }
    });
  10. Use VideoPlayerController extensions

    master

    FVP provides extensions to the standard VideoPlayerController to enable advanced features without switching to the Backend Player API.

    Available extended methods include:

    • snapshot()
    • record(String url)
    • fastSeekTo(Duration position)
    • setExternalSubtitle(String path)

    Example of using record():

    import 'package:fvp/fvp.dart' as fvp;
    
    fvp.registerWith(); // Ensure FVP is registered
    
    // After controller is initialized
    _controller.record('rtmp://127.0.0.1/live/test');
    import 'package:fvp/fvp.dart' as fvp;
    
    fvp.registerWith();
    
    // somewhere after controller is initialized
    _controller.record('rtmp://127.0.0.1/live/test');
  11. Configure FVP via registerWith()

    master

    You can customize which platforms use the FVP implementation and which decoders are used by passing an options map to fvp.registerWith().

    Platform Selection

    To limit FVP to specific platforms:

    fvp.registerWith(options: {'platforms': ['windows', 'macos', 'linux']});

    Decoder Selection

    To specify preferred decoders (e.g., for Windows):

    fvp.registerWith(options: {
        'video.decoders': ['D3D11', 'NVDEC', 'FFmpeg']
    });

    Subtitle Font

    To provide a remote URL for a fallback subtitle font:

    fvp.registerWith(options: {
        'subtitleFontFile': 'https://example.com/subfont.ttf'
    });

    Refer to the official documentation for a full list of available options.

    import 'package:fvp/fvp.dart' as fvp;
    
    fvp.registerWith(options: {
        'video.decoders': ['D3D11', 'NVDEC', 'FFmpeg'],
        'platforms': ['windows', 'macos', 'linux'],
        'subtitleFontFile': 'https://example.com/subfont.ttf'
    });
  12. Use the Backend Player API for custom players

    master

    If you need features beyond the standard video_player (such as playing from a specific position, looping in a range, or detailed media information), you can use the Backend Player API directly via mdk.dart.

    This API provides a more powerful interface than the VideoPlayerPlatform wrapper. You can reuse Player instances by changing Player.media instead of creating and disposing of them constantly.

    import 'package:fvp/mdk.dart';