vdocipher_flutter

VdoCipher plugin for flutter apps.

This project is a Flutter plugin package, that will enable video playback functionality by delegating to respective native libraries based on the platform.

Getting started

Run this command with Flutter:

$ flutter pub add vdocipher_flutter

This will add a line like this to your package's pubspec.yaml (and run an implicit dart pub get):

dependencies:
  vdocipher_flutter: ^1.1.0

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

Import it

Now in your Dart code, you can use:

import 'package:vdocipher_flutter/vdocipher_flutter.dart';

Example

samples.dart

import 'package:vdocipher_flutter/vdocipher_flutter.dart';

const EmbedInfo SAMPLE_1 = EmbedInfo.streaming(
    otp: '20160313versASE313BlEe9YKEaDuju5J0XcX2Z03Hrvm5rzKScvuyojMSBZBxfZ',
    playbackInfo: 'eyJ2aWRlb0lkIjoiM2YyOWI1NDM0YTVjNjE1Y2RhMThiMTZhNjIzMmZkNzUifQ==',
    embedInfoOptions: EmbedInfoOptions(
        autoplay: true
    )
);

const EmbedInfo SAMPLE_2 = EmbedInfo.streaming(
    otp: '20160313versASE313CBS0f0mkwrNqTswuCYx7Lo41GpQ3r06wbx2WgOUASrQIgH',
    playbackInfo: 'eyJ2aWRlb0lkIjoiYTllYWUwOTZjZDg4NGRiYmEzNTE1M2VlNDJhNTA0YTgifQ=='
);

vdoplayback_view.dart

import 'package:flutter/material.dart';
import 'package:vdocipher_flutter/vdocipher_flutter.dart';
import 'package:vdocipher_flutter_example/samples.dart';

class VdoPlaybackView extends StatefulWidget {

  @override
  _VdoPlaybackViewState createState() => _VdoPlaybackViewState();
}

class _VdoPlaybackViewState extends State<VdoPlaybackView> {
  VdoPlayerController? _controller;
  final double aspectRatio = 16/9;
  ValueNotifier<bool> _isFullScreen = ValueNotifier(false);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              Flexible(child: Container(
                child: VdoPlayer(
                  embedInfo: SAMPLE_1,
                  onPlayerCreated: (controller) => _onPlayerCreated(controller),
                  onFullscreenChange: _onFullscreenChange,
                  onError: _onVdoError,
                ),
                width: MediaQuery.of(context).size.width,
                height: _isFullScreen.value ? MediaQuery.of(context).size.height : _getHeightForWidth(MediaQuery.of(context).size.width),
              )),
              ValueListenableBuilder(
                  valueListenable: _isFullScreen,
                  builder: (context, dynamic value, child) {
                    return value ? SizedBox.shrink() : _nonFullScreenContent();
                  }),
            ])
    );
  }

  _onVdoError(VdoError vdoError)  {
    print("Oops, the system encountered a problem: " + vdoError.message);
  }

  _onPlayerCreated(VdoPlayerController? controller) {
    setState(() {
      _controller = controller;
      _onEventChange(_controller);
    });
  }

  _onEventChange(VdoPlayerController? controller) {
    controller!.addListener(() {
      VdoPlayerValue value = controller.value;

      print("VdoControllerListner"
          "\nloading: ${value.isLoading} "
          "\nplaying: ${value.isPlaying} "
          "\nbuffering: ${value.isBuffering} "
          "\nended: ${value.isEnded}"
      );
    });
  }

  _onFullscreenChange(isFullscreen) {
    setState(() {
      _isFullScreen.value = isFullscreen;
    });
  }

  _nonFullScreenContent() {
    return Column(
        children: [
          Text('Sample Playback', style: TextStyle(fontSize: 20.0),)
        ]);
  }

  double _getHeightForWidth(double width) {
    return width / aspectRatio;
  }
}

main.dart

import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:vdocipher_flutter/vdocipher_flutter.dart';
import 'package:vdocipher_flutter_example/vdoplayback_view.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'VdoCipher Sample Application',
      home: MyHome(),
      navigatorObservers: [VdoPlayerController.navigatorObserver('/player/(.*)')],
      theme: ThemeData(
          primaryColor: Colors.white,
          textTheme: TextTheme(bodyText1: TextStyle(fontSize: 12.0))),
    );
  }
}

class MyHome extends StatefulWidget {
  @override
  _MyHomeState createState() => _MyHomeState();
}

class _MyHomeState extends State<MyHome> {
  String? _nativePlatformLibraryVersion = 'Unknown';

  @override
  void initState() {
    super.initState();
    getNativeLibraryVersion();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> getNativeLibraryVersion() async {
    String? version;
    // Platform messages may fail, so we use a try/catch PlatformException.
    try {
      version = await (Platform.isIOS ? VdocipherMethodChannel.nativeIOSAndroidLibraryVersion : VdocipherMethodChannel.nativeAndroidLibraryVersion);
    } on PlatformException {
      version = 'Failed to get native platform library version.';
    }

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;

    setState(() {
      _nativePlatformLibraryVersion = version;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('VdoCipher Sample Application'),
        ),
        body: Center(child: Column(
          children: <Widget>[
            Expanded(child: Column(
                crossAxisAlignment: CrossAxisAlignment.center,
                children: <Widget>[
                  ElevatedButton(
                    onPressed: _goToVideoPlayback,
                    child: const Text('Online Playback',
                        style: TextStyle(fontSize: 20)),
                  ),
                  ElevatedButton(
                    onPressed: null,
                    child: const Text('Todo: video selection',
                        style: TextStyle(fontSize: 20)),
                  )
                ])),
            Padding(padding: EdgeInsets.all(16.0),
                child: Text('Native ${Platform.isIOS ? 'iOS' : 'Android'} library version: $_nativePlatformLibraryVersion',
                    style: TextStyle(color: Colors.grey, fontSize: 16.0)))
          ],
        ))
    );
  }

  void _goToVideoPlayback() {
    Navigator.of(context).push(
      MaterialPageRoute<void>(
        settings: RouteSettings(name: '/player/sample/video'),
        builder: (BuildContext context) {
          return VdoPlaybackView();
        },
      ),
    );
  }
}

VdoPlayer

Property Type Default / required Description
embedInfo EmbedInfo required Embed info object
onPlayerCreated(controller) Function(VdoController) required Callback function returns VdoController object
onFullscreenChange(isFullScreen) Function(bool isFullscreen) Optional Callback function returns true if full screen mode.
onError(error) Function(VdoError) Optional Callback function returns VdoError object
aspectRatio double Default 16:9 Aspect ratio
controls bool Default true Enables player controls, set false to disable player controls

EmbedInfo

Property Type Default / required Description
otp String required a valid OTP
playbackInfo String required A valid playbackinfo;
embedInfoOptions EmbedInfoOptions null Embed Info options
skipDuration Duration 10 seconds Forward/Backward skip duration
playbackSpeedOptions List<double> [0.75, 1.0, 1.25, 1.5, 1.75, 2.0] List of playback speed options between 0.25x to 2.25x

EmbedInfoOptions

Property Type Default / required Description
safetyNetApiKey String Optional A valid SafetyNetApiKey
preferredCaptionsLanguage Optional String Preferred caption language
startPosition Duration Optional Video start position
endPosition Duration Optional Video end position
resumePosition Duration Optional Vdeo resume position
maxVideoBitrateKbps int Optional Maximum video bitrate KBPS
bufferingGoalMs int Optional Buffering goal in MS
techOverride List<String> Optional Tech override list
disableAnalytics bool required (false) Disable analytics
autoplay bool required (true) Start autoplay
forceLowestBitrate bool required (false) Force lowest bitrate
forceHighestSupportedBitrate bool required (false) Force highest supported Bitrat

VdoController

Property Return Type Description
isPlaying bool Video playing
isBuffering bool Video buffering
isLoading bool Video loading
isEnded bool Video fully watched
isFullScreen ValueNotifier<bool> Video is in full screen or portrait mode
enterFullScreen(bool isFull) void Set full screen mode
load(EmbedInfo embedInfo) Future<LoadResult> Load video with embed info
play() Future<void> Play video
pause() Future<void> Pause video
stop() Future<void> Stop video
getDuration() Future<Duration> Get video duration
getPosition() Future<Duration> Get current video played position
seek(Duration target) Future<void> Seek video to target duration
setPlaybackSpeed(double speed) Future<void> Set playback speed
setCaptionLanguage(String language) Future<bool> Set Caption Language
navigatorObserver(String routePathOrRegex) void SwipeLeft event observer for iOS. Use inside MaterialApp(navigatorObservers: [])

VdoPlayerValue

Property Return Type Default / required Description
isLoading bool required Properties related to the currently loaded video.
mediaInfo MediaInfo required Total duration of the video.
duration Duration required This is Duration.zero if the video is not loaded.
position Duration required The current playback position.
bufferedPosition Duration required Position up to where the video is buffered.
skipDuration Duration required Skip Backword/Forward duration
isPlaying bool required True if the video is playing, false if paused.;
isBuffering bool required True if the video is buffering.;
isEnded bool required True if the currently loaded video has played to the end.
playbackSpeed double required The current playback speed.
playbackSpeedOptions List<double> required The list of available playback speed options.
isAdaptive bool required True if track selection is done in adaptive mode, false if a track has been selected explicitly.
audioTrack AudioTrack Optional Currently selected audio track.
videoTrack VideoTrack Optional Currently selected video track.
subtitleTrack SubtitleTrack Optional Currently selected subtitle track.
audioTracks List<AudioTrack> Optional List of all available audio tracks.;
videoTracks List<VideoTrack> Optional List of all available video tracks.;
subtitleTracks List<SubtitleTrack> Optional List of all available subtitle tracks.
vdoError VdoError Optional If not null, this gives details about an error encountered while loading the video or during playback.

MediaInfo

Property Type Default / required Description
mediaId String required Media ID in string
type enum MediaInfoType {streaming, offline} required Media type
duration Duration required Media duration
title String Optional Media title
description String Optional Media description

AudioTrack

Property Type Default / required Description
id int required A unique identifier for the track in a playback session
language String Optional Language code for the track;
bitrate int Optional Bitrate in kbps

VideoTrack

Property Type Default / required Description
id int required A unique identifier for the track in a playback session
bitrate int Optional Bitrate in kbps;
width int Optional Width of the track in px
height int Optional Height of the track in px

SubtitleTrack

Property Type Default / required Description
id int required A unique identifier for the track in a playback session;
language String Optional Language code for the track;

VdoError

Property Type Default / required Description
code int required Error code
message String required Error message
httpStatusCode int Optional HTTP Status Code

Libraries

vdocipher_flutter
VdoCipher Flutter plugin