Im trying to do a basic implementation of IVS player for flutter given that it seems to be the lowest latency player for streaming. There seems to be a flutter package: https://pub.dev/packages/ivs_player but it lacks documentation or even a github repositry, plus the example is not very telling, I couldn't make it work, if anybody has a working example I will greatly appreciate that you share it.
I tried to create a plugin base on the native implementation from the Amazon's IVS Player SDK, I hear the audio but I don't see the video.
IVSPlayerManager.swift
import Foundation
import AmazonIVSPlayer
class IVSPlayerManager {
var player: IVSPlayer!
init() {
player = IVSPlayer()
}
func play(url: String) {
guard let streamURL = URL(string: url) else { return }
player.load(streamURL)
player.play()
}
func dispose() {
player.pause()
player = nil
}
// Other necessary functions
}
IVSPlayerViewFactory.swift
import Foundation
import Flutter
import UIKit
import AmazonIVSPlayer
class IVSPlayerViewFactory: NSObject, FlutterPlatformViewFactory {
func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
return IVSPlayerFlutterView(frame: frame, viewId: viewId, args: args)
}
}
IVSPlayerView.swift
import UIKit
import AmazonIVSPlayer
import Flutter
class IVSPlayerFlutterView: NSObject, FlutterPlatformView {
private var player: IVSPlayer
private var ivsPlayerView: IVSPlayerView
init(frame: CGRect, viewId: Int64, args: Any?) {
self.player = IVSPlayer()
self.ivsPlayerView = IVSPlayerView(frame: frame)
super.init()
self.ivsPlayerView.player = player
setupPlayer()
}
func view() -> UIView {
return ivsPlayerView
}
private func setupPlayer() {
// Load and play the stream URL as needed
if let url = URL(string: "Streaming URL") {
player.load(url)
}
}
}
AppDelegate.swift
import UIKit
import Flutter
import flutter_local_notifications
@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
var ivsPlayerManager: IVSPlayerManager?
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
// Register plugins with the Flutter framework
FlutterLocalNotificationsPlugin.setPluginRegistrantCallback { (registry) in
GeneratedPluginRegistrant.register(with: registry)
}
GeneratedPluginRegistrant.register(with: self)
// Set up the Flutter view controller
let controller: FlutterViewController = window?.rootViewController as! FlutterViewController
// Set up the flavor channel
let flavorChannel = FlutterMethodChannel(name: "flavor", binaryMessenger: controller.binaryMessenger)
flavorChannel.setMethodCallHandler({
(call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
let flavor = Bundle.main.infoDictionary?["Flavor"] as? String
result(flavor)
})
// Set up notification center delegate for iOS 10.0+
if #available(iOS 10.0, *) {
UNUserNotificationCenter.current().delegate = self as? UNUserNotificationCenterDelegate
}
// Initialize IVS Player Manager
ivsPlayerManager = IVSPlayerManager()
// Set up the IVS channel
let ivsChannel = FlutterMethodChannel(name: "com.example.ivs_player", binaryMessenger: controller.binaryMessenger)
ivsChannel.setMethodCallHandler { (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
if call.method == "play", let args = call.arguments as? [String: Any], let url = args["url"] as? String {
self.ivsPlayerManager?.play(url: url)
}
else if call.method == "dispose" {
// Dispose logic for the player
self.ivsPlayerManager?.dispose()
}
else {
result(FlutterMethodNotImplemented)
}
}
// Register IVS Player View Factory
let registrar = self.registrar(forPlugin: "plugin-name")
registrar?.register(IVSPlayerViewFactory(), withId: "ivs_player_view")
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
And this is the flutter part:
class IvsVideoPlayer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return SizedBox(
height: 300, // Example height
width: 300, // Example width
child: Platform.isIOS ? UiKitView(
viewType: 'ivs_player_view',
onPlatformViewCreated: _onPlatformViewCreated,
) : AndroidView(
viewType: 'ivs_player_view',
onPlatformViewCreated: _onPlatformViewCreated,
),
);
}
void _onPlatformViewCreated(int id) {
// Platform view created logic
}
}
IVSPlayerController.dart
class IvsPlayerController {
static const MethodChannel _channel = MethodChannel('com.example.ivs_player');
Future<void> play(String url) async {
await _channel.invokeMethod('play', {'url': url});
}
Future<void> dispose() async {
await _channel.invokeMethod('dispose');
}
}
And this an example on how I'm using the plugin:
class VideoScreen extends StatefulWidget {
@override
_VideoScreenState createState() => _VideoScreenState();
}
class _VideoScreenState extends State<VideoScreen> {
final IvsPlayerController _ivsController = IvsPlayerController();
@override
void dispose() {
_ivsController.dispose();
super.dispose();
}
@override
void initState() {
super.initState();
_ivsController.play('Streaming_URL.m3u8');
}
@override
Widget build(BuildContext context) {
return Scaffold(
body:
IvsVideoPlayer()
);
}}