flutter视频播放器video_player_avfoundation之AVFoundationVideoPlayer(三)

flutter端的AVFoundationVideoPlayer是实现PlatformInterface接口的插件。它就是flutter端跟原生端通信的桥梁。

AVFoundationVideoPlayer

scss 复制代码
/// iOS平台的视频播放器实现,使用Pigeon生成的VideoPlayerApi
class AVFoundationVideoPlayer extends VideoPlayerPlatform {
  /// 创建一个新的基于AVFoundation的视频播放器实现实例
  AVFoundationVideoPlayer({
    @visibleForTesting AVFoundationVideoPlayerApi? pluginApi,
    @visibleForTesting VideoPlayerInstanceApi Function(int playerId)? playerProvider,
  }) : _api = pluginApi ?? AVFoundationVideoPlayerApi(),
       _playerProvider = playerProvider ?? _productionApiProvider;

  final AVFoundationVideoPlayerApi _api;

  // 用于创建VideoPlayerInstanceApi实例的方法,可以在测试中被重写
  final VideoPlayerInstanceApi Function(int mapId) _playerProvider;

  /// 将播放器ID与视图状态关联的映射表
  /// 用于确定构建视图时使用哪种视图类型
  @visibleForTesting
  final Map<int, VideoPlayerViewState> playerViewStates = <int, VideoPlayerViewState>{};

  final Map<int, VideoPlayerInstanceApi> _players = <int, VideoPlayerInstanceApi>{};

  /// 将此类注册为VideoPlayerPlatform的默认实例
  static void registerWith() {
    VideoPlayerPlatform.instance = AVFoundationVideoPlayer();
  }

  @override
  Future<void> init() {
    return _api.initialize();
  }

  @override
  Future<void> dispose(int playerId) async {
    final VideoPlayerInstanceApi? player = _players.remove(playerId);
    await player?.dispose();
    playerViewStates.remove(playerId);
  }

  @override
  Future<int?> create(DataSource dataSource) async {
    return createWithOptions(
      VideoCreationOptions(
        dataSource: dataSource,
        // 在引入createWithOptions之前,纹理视图是唯一支持的视图类型
        viewType: VideoViewType.textureView,
      ),
    );
  }

  @override
  Future<int?> createWithOptions(VideoCreationOptions options) async {
    final DataSource dataSource = options.dataSource;
    final VideoViewType viewType = options.viewType;

    String? uri;
    switch (dataSource.sourceType) {
      case DataSourceType.asset:
        final String? asset = dataSource.asset;
        if (asset == null) {
          throw ArgumentError('"asset"对于资源数据源必须非空');
        }
        uri = await _api.getAssetUrl(asset, dataSource.package);
        if (uri == null) {
          // 为了与之前的实现兼容,抛出平台异常
          throw PlatformException(code: 'video_player', message: '在包${dataSource.package}中找不到资源$asset');
        }
      case DataSourceType.network:
      case DataSourceType.file:
      case DataSourceType.contentUri:
        uri = dataSource.uri;
    }
    if (uri == null) {
      throw ArgumentError('无法从$options构造视频资源');
    }
    final CreationOptions pigeonCreationOptions = CreationOptions(uri: uri, httpHeaders: dataSource.httpHeaders);

    final int playerId;
    final VideoPlayerViewState state;
    switch (viewType) {
      case VideoViewType.textureView:
        final TexturePlayerIds ids = await _api.createForTextureView(pigeonCreationOptions);
        playerId = ids.playerId;
        state = VideoPlayerTextureViewState(textureId: ids.textureId);
      case VideoViewType.platformView:
        playerId = await _api.createForPlatformView(pigeonCreationOptions);
        state = const VideoPlayerPlatformViewState();
    }
    playerViewStates[playerId] = state;
    ensureApiInitialized(playerId);

    return playerId;
  }

  /// 返回playerId对应的API实例,如果不存在则创建它
  @visibleForTesting
  VideoPlayerInstanceApi ensureApiInitialized(int playerId) {
    return _players.putIfAbsent(playerId, () {
      return _playerProvider(playerId);
    });
  }

  @override
  Future<void> setLooping(int playerId, bool looping) {
    return _playerWith(id: playerId).setLooping(looping);
  }

  @override
  Future<void> play(int playerId) {
    return _playerWith(id: playerId).play();
  }

  @override
  Future<void> pause(int playerId) {
    return _playerWith(id: playerId).pause();
  }

  @override
  Future<void> setVolume(int playerId, double volume) {
    return _playerWith(id: playerId).setVolume(volume);
  }

  @override
  Future<void> setPlaybackSpeed(int playerId, double speed) {
    assert(speed > 0);
    return _playerWith(id: playerId).setPlaybackSpeed(speed);
  }

  @override
  Future<void> seekTo(int playerId, Duration position) {
    return _playerWith(id: playerId).seekTo(position.inMilliseconds);
  }

  @override
  Future<Duration> getPosition(int playerId) async {
    final int position = await _playerWith(id: playerId).getPosition();
    return Duration(milliseconds: position);
  }

  @override
  Stream<VideoEvent> videoEventsFor(int playerId) {
    debugPrint('---✅dart启动视频播放器流监听videoEventsFor, playerId: $playerId✅---');
    return _eventChannelFor(playerId).receiveBroadcastStream().map((dynamic event) {
      final Map<dynamic, dynamic> map = event as Map<dynamic, dynamic>;
      debugPrint('---✅dart视频播放器流监听videoEventsFor结果, map: $map✅---');
      return switch (map['event']) {
        'initialized' => VideoEvent(
          eventType: VideoEventType.initialized,
          duration: Duration(milliseconds: map['duration'] as int),
          size: Size((map['width'] as num?)?.toDouble() ?? 0.0, (map['height'] as num?)?.toDouble() ?? 0.0),
        ),
        'completed' => VideoEvent(eventType: VideoEventType.completed),
        'bufferingUpdate' => VideoEvent(
          buffered: (map['values'] as List<dynamic>).map<DurationRange>(_toDurationRange).toList(),
          eventType: VideoEventType.bufferingUpdate,
        ),
        'bufferingStart' => VideoEvent(eventType: VideoEventType.bufferingStart),
        'bufferingEnd' => VideoEvent(eventType: VideoEventType.bufferingEnd),
        'isPlayingStateUpdate' => VideoEvent(eventType: VideoEventType.isPlayingStateUpdate, isPlaying: map['isPlaying'] as bool),
        _ => VideoEvent(eventType: VideoEventType.unknown),
      };
    });
  }

  @override
  Future<void> setMixWithOthers(bool mixWithOthers) {
    return _api.setMixWithOthers(mixWithOthers);
  }

  @override
  Widget buildView(int playerId) {
    return buildViewWithOptions(VideoViewOptions(playerId: playerId));
  }

  @override
  Widget buildViewWithOptions(VideoViewOptions options) {
    final int playerId = options.playerId;
    final VideoPlayerViewState? viewState = playerViewStates[playerId];

    return switch (viewState) {
      VideoPlayerTextureViewState(:final int textureId) => Texture(textureId: textureId),
      VideoPlayerPlatformViewState() => _buildPlatformView(playerId),
      null => throw Exception('找不到playerId对应的视图类型: $playerId'),
    };
  }

  Widget _buildPlatformView(int playerId) {
    final PlatformVideoViewCreationParams creationParams = PlatformVideoViewCreationParams(playerId: playerId);

    return IgnorePointer(
      // 使用IgnorePointer以便在平台视图上方使用GestureDetector
      child: UiKitView(
        viewType: 'plugins.flutter.dev/video_player_ios',
        creationParams: creationParams,
        creationParamsCodec: AVFoundationVideoPlayerApi.pigeonChannelCodec,
      ),
    );
  }

  EventChannel _eventChannelFor(int playerId) {
    return EventChannel('flutter.io/videoPlayer/videoEvents$playerId');
  }

  VideoPlayerInstanceApi _playerWith({required int id}) {
    final VideoPlayerInstanceApi? player = _players[id];
    return player ?? (throw StateError('没有ID为$id的活跃播放器'));
  }

  DurationRange _toDurationRange(dynamic value) {
    final List<dynamic> pair = value as List<dynamic>;
    final int startMilliseconds = pair[0] as int;
    final int durationMilliseconds = pair[1] as int;
    return DurationRange(
      Duration(milliseconds: startMilliseconds),
      Duration(milliseconds: startMilliseconds + durationMilliseconds),
    );
  }
}

AVFoundationVideoPlayerApi

php 复制代码
/**
 * AVFoundation视频播放器API
 * 
 * 这是一个由Pigeon工具自动生成的类,用于Flutter与原生iOS/macOS平台之间的通信。
 * 该类提供了视频播放器的核心平台级别操作接口。
 * 
 * 主要功能:
 * 1. 播放器初始化和生命周期管理
 * 2. 创建不同渲染模式的播放器(平台视图/纹理视图)
 * 3. 音频会话配置管理
 * 4. Flutter资源文件路径解析
 * 
 * 通信机制:
 * - 使用BasicMessageChannel进行跨平台消息传递
 * - 支持异步操作和错误处理
 * - 自动处理数据序列化和反序列化
 */
class AVFoundationVideoPlayerApi {
  /// AVFoundationVideoPlayerApi构造函数
  /// 
  /// [binaryMessenger] 二进制消息传递器参数,用于依赖注入。
  /// 如果为null,将使用默认的BinaryMessenger路由到宿主平台。
  /// 
  /// [messageChannelSuffix] 消息通道后缀,用于区分不同的API实例
  AVFoundationVideoPlayerApi({
    BinaryMessenger? binaryMessenger,
    String messageChannelSuffix = '',
  }) : pigeonVar_binaryMessenger = binaryMessenger,
       pigeonVar_messageChannelSuffix =
           messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
           
  /// 二进制消息传递器实例,用于与原生平台通信
  final BinaryMessenger? pigeonVar_binaryMessenger;

  /// Pigeon消息编解码器,处理数据类型转换
  static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();

  /// 消息通道后缀,用于标识特定的API实例
  final String pigeonVar_messageChannelSuffix;

  /**
   * 初始化AVFoundation视频播放器插件
   * 
   * 这是使用播放器之前必须调用的方法,用于:
   * - 设置AVFoundation框架的基础配置
   * - 初始化音频会话
   * - 准备播放器工厂和相关组件
   * 
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当初始化失败时抛出平台异常
   */
  Future<void> initialize() async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.initialize$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }

  /**
   * 创建使用平台视图渲染的视频播放器
   * 
   * 平台视图模式特点:
   * - 使用原生UIView/NSView进行渲染
   * - 更好的兼容性,支持所有视频格式和特性
   * - 可能存在性能开销和层级问题
   * - 适用于需要完整原生功能的场景
   * 
   * @param params 创建选项,包含视频URI和HTTP头信息
   * @return Future<int> 返回创建的播放器ID
   * @throws PlatformException 当创建失败时抛出异常
   */
  Future<int> createForPlatformView(CreationOptions params) async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.createForPlatformView$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
      <Object?>[params],
    );
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else if (pigeonVar_replyList[0] == null) {
      throw PlatformException(
        code: 'null-error',
        message: 'Host platform returned null value for non-null return value.',
      );
    } else {
      return (pigeonVar_replyList[0] as int?)!;
    }
  }

  /**
   * 创建使用纹理渲染的视频播放器
   * 
   * 纹理模式特点:
   * - 使用Flutter的Texture Widget进行渲染
   * - 更好的性能表现和Flutter集成
   * - 支持Flutter的变换、动画等效果
   * - 可能在某些特殊视频格式上有限制
   * - 推荐用于大多数常规播放场景
   * 
   * @param creationOptions 创建选项,包含视频URI和HTTP头信息
   * @return Future<TexturePlayerIds> 返回包含播放器ID和纹理ID的对象
   * @throws PlatformException 当创建失败时抛出异常
   */
  Future<TexturePlayerIds> createForTextureView(
    CreationOptions creationOptions,
  ) async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.createForTextureView$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
      <Object?>[creationOptions],
    );
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else if (pigeonVar_replyList[0] == null) {
      throw PlatformException(
        code: 'null-error',
        message: 'Host platform returned null value for non-null return value.',
      );
    } else {
      return (pigeonVar_replyList[0] as TexturePlayerIds?)!;
    }
  }

  /**
   * 设置音频混合模式
   * 
   * 控制视频播放器的音频是否与其他应用的音频混合播放:
   * - true: 允许与其他音频混合(如音乐应用、通话等)
   * - false: 独占音频输出,会暂停其他应用的音频
   * 
   * 使用场景:
   * - 背景音乐播放:设置为true,允许与系统音频混合
   * - 视频通话、游戏:设置为false,获得独占音频控制
   * 
   * @param mixWithOthers 是否允许与其他音频混合
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当设置失败时抛出异常
   */
  Future<void> setMixWithOthers(bool mixWithOthers) async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.setMixWithOthers$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
      <Object?>[mixWithOthers],
    );
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }

  /**
   * 获取Flutter资源文件的本地URL路径
   * 
   * 将Flutter项目中的资源文件路径转换为原生平台可访问的本地文件URL。
   * 这对于播放打包在应用内的视频文件非常重要。
   * 
   * 资源路径解析过程:
   * 1. 根据资源名称在Flutter资源清单中查找
   * 2. 考虑包名(如果指定)进行路径解析
   * 3. 返回原生平台可直接访问的file:// URL
   * 
   * @param asset 资源文件名称(如 "videos/sample.mp4")
   * @param package 可选的包名,用于访问其他包中的资源
   * @return Future<String?> 返回本地文件URL,如果资源不存在则返回null
   * @throws PlatformException 当路径解析失败时抛出异常
   */
  Future<String?> getAssetUrl(String asset, String? package) async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.AVFoundationVideoPlayerApi.getAssetUrl$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
      <Object?>[asset, package],
    );
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return (pigeonVar_replyList[0] as String?);
    }
  }
}

VideoPlayerInstanceApi

ini 复制代码
/**
 * 视频播放器实例API
 * 
 * 这是一个由Pigeon工具自动生成的类,用于控制单个视频播放器实例的播放行为。
 * 该类提供了视频播放器的核心控制功能,每个播放器实例都有一个对应的API实例。
 * 
 * 主要功能:
 * 1. 播放控制(播放、暂停、跳转)
 * 2. 播放参数设置(音量、播放速度、循环模式)
 * 3. 播放状态查询(当前播放位置)
 * 4. 资源管理(释放播放器资源)
 * 
 * 使用方式:
 * - 通过AVFoundationVideoPlayerApi创建播放器后获得实例
 * - 使用messageChannelSuffix区分不同的播放器实例
 * - 所有操作都是异步的,返回Future对象
 */
class VideoPlayerInstanceApi {
  /// VideoPlayerInstanceApi构造函数
  /// 
  /// [binaryMessenger] 二进制消息传递器参数,用于依赖注入。
  /// 如果为null,将使用默认的BinaryMessenger路由到宿主平台。
  /// 
  /// [messageChannelSuffix] 消息通道后缀,用于标识特定的播放器实例
  /// 通常使用播放器ID作为后缀,确保每个播放器实例有独立的通信通道
  VideoPlayerInstanceApi({
    BinaryMessenger? binaryMessenger,
    String messageChannelSuffix = '',
  }) : pigeonVar_binaryMessenger = binaryMessenger,
       pigeonVar_messageChannelSuffix =
           messageChannelSuffix.isNotEmpty ? '.$messageChannelSuffix' : '';
           
  /// 二进制消息传递器实例,用于与原生平台通信
  final BinaryMessenger? pigeonVar_binaryMessenger;

  /// Pigeon消息编解码器,处理数据类型转换
  static const MessageCodec<Object?> pigeonChannelCodec = _PigeonCodec();

  /// 消息通道后缀,用于标识特定的播放器实例
  final String pigeonVar_messageChannelSuffix;

  /**
   * 设置视频循环播放模式
   * 
   * 控制视频播放完成后的行为:
   * - true: 视频播放完成后自动重新开始播放,形成无限循环
   * - false: 视频播放完成后停止,不会自动重播
   * 
   * 使用场景:
   * - 背景视频、装饰性视频:通常设置为true,持续循环播放
   * - 教学视频、宣传片:通常设置为false,播放完成后停止
   * - 短视频应用:可根据用户设置或内容类型动态调整
   * 
   * @param looping 是否启用循环播放
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当设置失败时抛出异常
   */
  Future<void> setLooping(bool looping) async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.VideoPlayerInstanceApi.setLooping$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
      <Object?>[looping],
    );
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }

  /**
   * 设置视频播放音量
   * 
   * 调整当前播放器实例的音频输出音量大小。
   * 这个设置只影响当前播放器,不会改变系统全局音量。
   * 
   * 音量范围和效果:
   * - 0.0: 完全静音,无音频输出
   * - 1.0: 最大音量,使用视频原始音频级别
   * - 0.0-1.0之间: 按比例调整音量大小
   * - 超出范围的值会被自动限制在有效范围内
   * 
   * 使用场景:
   * - 多媒体应用中的音量控制滑块
   * - 背景视频的音量调节
   * - 音频淡入淡出效果实现
   * 
   * @param volume 音量值,范围0.0-1.0
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当设置失败时抛出异常
   */
  Future<void> setVolume(double volume) async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.VideoPlayerInstanceApi.setVolume$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
      <Object?>[volume],
    );
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }

  /**
   * 设置视频播放速度
   * 
   * 调整视频播放的速率,可以实现快进、慢放、倒放等效果。
   * 播放速度的改变会同时影响视频和音频的播放速率。
   * 
   * 速度值说明:
   * - 1.0: 正常播放速度(默认值)
   * - 0.5: 半速播放(慢放)
   * - 2.0: 双倍速播放(快进)
   * - 0.0: 暂停播放
   * - 负值: 倒放(部分平台支持)
   * 
   * 常用速度设置:
   * - 0.25x, 0.5x, 0.75x: 慢速播放,适用于学习、分析场景
   * - 1.25x, 1.5x, 2.0x: 快速播放,适用于快速浏览
   * - 变速播放在在线教育、体育分析等场景中非常有用
   * 
   * @param speed 播放速度倍率
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当设置失败时抛出异常
   */
  Future<void> setPlaybackSpeed(double speed) async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.VideoPlayerInstanceApi.setPlaybackSpeed$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
      <Object?>[speed],
    );
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }

  /**
   * 开始播放视频
   * 
   * 启动或恢复视频播放。如果视频处于暂停状态,将从当前位置继续播放;
   * 如果视频尚未开始,将从头开始播放。
   * 
   * 播放行为说明:
   * - 首次调用:从视频开头开始播放
   * - 暂停后调用:从暂停位置继续播放
   * - 播放完成后调用:根据循环设置决定是否重新播放
   * - 可以在视频加载过程中调用,播放器会在准备就绪后自动开始
   * 
   * 注意事项:
   * - 某些平台可能需要用户交互才能开始播放(自动播放策略)
   * - 网络视频需要缓冲时间,可能不会立即开始播放
   * - 播放状态变化会通过事件流通知Flutter层
   * 
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当播放启动失败时抛出异常
   */
  Future<void> play() async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.VideoPlayerInstanceApi.play$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }

  /**
   * 获取当前播放位置
   * 
   * 返回视频当前的播放进度,以毫秒为单位。
   * 这个值表示从视频开始到当前播放点的时间长度。
   * 
   * 返回值说明:
   * - 返回值为毫秒数(int类型)
   * - 视频开始位置为0
   * - 播放过程中该值会持续增加
   * - 跳转后会立即反映新的位置
   * 
   * 使用场景:
   * - 实现播放进度条显示
   * - 保存播放断点,支持续播功能
   * - 实现播放时间显示(需要转换为时分秒格式)
   * - 同步多个播放器的播放进度
   * 
   * 注意事项:
   * - 频繁调用可能影响性能,建议配合定时器适度查询
   * - 网络视频的位置可能不够精确,存在缓冲影响
   * 
   * @return Future<int> 当前播放位置(毫秒)
   * @throws PlatformException 当获取位置失败时抛出异常
   */
  Future<int> getPosition() async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.VideoPlayerInstanceApi.getPosition$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else if (pigeonVar_replyList[0] == null) {
      throw PlatformException(
        code: 'null-error',
        message: 'Host platform returned null value for non-null return value.',
      );
    } else {
      return (pigeonVar_replyList[0] as int?)!;
    }
  }

  /**
   * 跳转到指定播放位置
   * 
   * 将视频播放位置跳转到指定的时间点。这是一个异步操作,
   * 跳转完成后播放器会从新位置继续播放或保持暂停状态。
   * 
   * 参数说明:
   * - position: 目标位置,以毫秒为单位
   * - 可以跳转到视频的任意有效位置
   * - 超出视频长度的值会被限制到视频末尾
   * - 负值会被限制到视频开头(0位置)
   * 
   * 跳转行为:
   * - 播放中跳转:会在新位置继续播放
   * - 暂停中跳转:会跳转到新位置但保持暂停状态
   * - 网络视频跳转:可能需要重新缓冲
   * 
   * 使用场景:
   * - 进度条拖拽跳转
   * - 章节跳转功能
   * - 续播功能(跳转到上次播放位置)
   * - 精确定位到特定时间点
   * 
   * @param position 目标播放位置(毫秒)
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当跳转失败时抛出异常
   */
  Future<void> seekTo(int position) async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.VideoPlayerInstanceApi.seekTo$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(
      <Object?>[position],
    );
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }

  /**
   * 暂停视频播放
   * 
   * 暂停当前正在播放的视频,保持在当前播放位置。
   * 暂停后可以通过调用play()方法从当前位置恢复播放。
   * 
   * 暂停行为说明:
   * - 立即停止视频和音频播放
   * - 保持当前播放位置不变
   * - 可以多次调用,不会产生副作用
   * - 如果视频已经暂停,调用此方法无效果
   * 
   * 使用场景:
   * - 用户主动暂停播放
   * - 应用进入后台时自动暂停
   * - 接收到电话等中断事件时暂停
   * - 实现播放/暂停切换功能
   * 
   * 与其他操作的关系:
   * - 暂停后仍可以调用seekTo()跳转位置
   * - 暂停后可以调用setVolume()等设置方法
   * - 播放状态变化会通过事件流通知Flutter层
   * 
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当暂停操作失败时抛出异常
   */
  Future<void> pause() async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.VideoPlayerInstanceApi.pause$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }

  /**
   * 释放播放器资源
   * 
   * 彻底释放当前播放器实例占用的所有系统资源,包括内存、解码器、
   * 网络连接等。调用此方法后,播放器实例将不再可用。
   * 
   * 释放操作包括:
   * - 停止视频播放和音频输出
   * - 释放视频解码器和音频解码器
   * - 关闭网络连接和文件句柄
   * - 清理缓存和临时数据
   * - 注销事件监听器和KVO观察者
   * 
   * 调用时机:
   * - 播放器不再需要时(如页面销毁)
   * - 应用内存不足时主动释放
   * - 切换到新的视频源之前
   * - 应用进入后台长时间不使用时
   * 
   * 重要注意事项:
   * - 调用dispose()后不能再使用此播放器实例
   * - 必须在适当的时机调用,避免内存泄漏
   * - Flutter Widget销毁时应确保调用此方法
   * - 这是一个不可逆操作,无法恢复播放器状态
   * 
   * @return Future<void> 异步操作完成标识
   * @throws PlatformException 当资源释放失败时抛出异常
   */
  Future<void> dispose() async {
    final String pigeonVar_channelName =
        'dev.flutter.pigeon.video_player_avfoundation.VideoPlayerInstanceApi.dispose$pigeonVar_messageChannelSuffix';
    final BasicMessageChannel<Object?> pigeonVar_channel =
        BasicMessageChannel<Object?>(
          pigeonVar_channelName,
          pigeonChannelCodec,
          binaryMessenger: pigeonVar_binaryMessenger,
        );
    final Future<Object?> pigeonVar_sendFuture = pigeonVar_channel.send(null);
    final List<Object?>? pigeonVar_replyList =
        await pigeonVar_sendFuture as List<Object?>?;
    if (pigeonVar_replyList == null) {
      throw _createConnectionError(pigeonVar_channelName);
    } else if (pigeonVar_replyList.length > 1) {
      throw PlatformException(
        code: pigeonVar_replyList[0]! as String,
        message: pigeonVar_replyList[1] as String?,
        details: pigeonVar_replyList[2],
      );
    } else {
      return;
    }
  }
}
相关推荐
Asort2 小时前
JavaScript设计模式(六)——适配器模式 (Adapter)
前端·javascript·设计模式
是晓晓吖2 小时前
Puppeteer page.on('response',fn)的最佳实践之等待响应
前端·puppeteer
跟橙姐学代码2 小时前
给Python项目加个“隔离间”,从此告别依赖纠缠!
前端·python·ipython
Cache技术分享2 小时前
202. Java 异常 - throw 语句的使用
前端·后端
_AaronWong2 小时前
Electron全局搜索框实战:快捷键调起+实时高亮+多窗口支持
前端·搜索引擎·electron
笔尖的记忆2 小时前
渲染引擎详解
前端
大明二代2 小时前
为 Angular Material 应用添加完美深色模式支持
前端
Mintopia3 小时前
🚪 当 Next.js 中间件穿上保安制服:请求拦截与权限控制的底层奇幻之旅
前端·后端·next.js