hm_video_player 0.5.1 copy "hm_video_player: ^0.5.1" to clipboard
hm_video_player: ^0.5.1 copied to clipboard

跨平台视频播放器插件,支持全屏、画中画、投屏、倍速等功能。

hm_video_player #

Native PlatformView video player with Mohe-style fullscreen transition.

Flutter and native communicate through Pigeon-generated type-safe APIs.

Supports HTTP(S) streams and local media (file://, absolute paths; Android also content://).

Installation #

Add to pubspec.yaml:

dependencies:
  hm_video_player: ^0.5.1

Then run flutter pub get.

Package #

Item Value
Dart package hm_video_player
Android package com.hm.video_player
Plugin class HmVideoPlayerPlugin
PlatformView type com.hm.video_player/view

Public API #

import 'package:hm_video_player/hm_video_player.dart';

final controller = HmVideoPlayerController();

HmVideoPlayer(
  controller: controller,
  videoUrl: url,
  title: 'Demo',
  qualities: [VideoQuality(label: 'HD', url: url)],
  episodes: [VideoEpisode(title: 'Ep 1', url: url)],
);

// Control
await controller.play();
await controller.pause();
await controller.seekTo(Duration(seconds: 5));
await controller.setSpeed(1.5);
await controller.setVolume(0.8);
await controller.setMuted(false);
await controller.enterFullscreen();
await controller.enterPictureInPicture();
await controller.exitPictureInPicture();
await controller.setPictureInPictureEnabled(true);
await controller.setAutoEnterPictureInPicture(false);
await controller.setAutoRotateFullscreen(true);

// Query
final position = await controller.position;
final duration = await controller.duration;
final playing = await controller.isPlaying;
final inPip = await controller.isInPictureInPicture;
final pipSupported = await controller.isPictureInPictureSupported;

// Typed events
controller.events.listen((event) {
  switch (event) {
    case ProgressEvent(:final position, :final duration):
      break;
    case FullscreenOpenedEvent():
      break;
    case FullscreenClosedEvent():
      break;
    case PipOpenedEvent():
      break;
    case PipClosedEvent():
      break;
    default:
      break;
  }
});

Architecture #

lib/                          Public Dart API
  hm_video_player.dart
  src/
    platform/messages.g.dart  Pigeon generated (do not edit)
pigeons/messages.dart         Pigeon contract (edit here)
android/.../com/hm/video_player/
ios/Classes/

Regenerate Pigeon bindings after changing pigeons/messages.dart:

bash tool/generate_pigeon.sh

Future capabilities (danmaku, subtitles, etc.) should add a separate @HostApi in pigeons/messages.dart and share the same per-view messageChannelSuffix.

Host app (Android) #

Picture-in-picture requires the host Activity to declare PiP support:

<activity
    android:name=".MainActivity"
    android:supportsPictureInPicture="true">

supportsPictureInPicture is required on the host Activity. PiP state is tracked via activity lifecycle callbacks in the plugin; no extra configChanges flag is needed.

Host app (iOS) #

Forward orientation support to the plugin:

import hm_video_player

override func application(
  _ application: UIApplication,
  supportedInterfaceOrientationsFor window: UIWindow?
) -> UIInterfaceOrientationMask {
  return HmVideoPlayerPlugin.orientationMask
}

Run example #

cd example
flutter pub get
flutter run

Notes #

  • Inline and fullscreen both use the native player (ExoPlayer / AVPlayer).
  • Fullscreen transition logic is unchanged from the Mohe-style implementation.
  • danmakuItems is reserved for a future DanmakuHostApi.
  • trialDuration is wired: native pauses and emits TrialEndedEvent when the limit is reached.
  • Picture-in-picture: use enablePictureInPicture / autoEnterPictureInPicture on [HmVideoPlayer] for initial state when the PlatformView is created. For runtime control (e.g. VIP gating), call setPictureInPictureEnabled / setAutoEnterPictureInPicture on the controller before updating Flutter UI state. Disabling the master switch exits PiP if active; disabling auto-enter only stops background auto PiP—manual enterPictureInPicture() still works. PiP is disabled during cast. See docs/API.md for platform details. Example: example/lib/main.dart.
  • Auto fullscreen on rotation: use autoRotateFullscreen on [HmVideoPlayer] for initial state; call setAutoRotateFullscreen on the controller at runtime to enable/disable sensor-based fullscreen entry while keeping manual fullscreen available.
  • Touch gestures (Tencent Video style): horizontal seek, left brightness, right system volume, center long-press speed boost. Inline drag gestures can be disabled via enableInlineDragGestures; inline double-tap via enableInlineDoubleTapPlayPause. Fullscreen always supports all gestures. See docs/API.md for UI hints and platform notes (iOS volume gesture requires a physical device).

Cast (投屏) #

默认 castUiMode: HmCastUiMode.flutter:点击播放器投屏按钮时,原生层只发送 CastRequestedEvent,由业务层跳转自定义投屏页。原生负责设备发现、协议连接与 castStateChanged 生命周期事件。

协议支持矩阵 #

协议 Android iOS Flutter 投屏页
DLNA 支持 支持 设备列表 + connectCast(deviceId)
Chromecast 支持 支持(需初始化 GCKCastContext) 设备列表 + connectCast(deviceId)
AirPlay 不支持 支持 presentAirPlayPicker() 打开系统选择器

业务集成 #

HmVideoPlayer(
  controller: controller,
  videoUrl: url,
  castUiMode: HmCastUiMode.flutter, // 默认
);

controller.events.listen((event) {
  if (event is CastRequestedEvent) {
    Navigator.of(context).push(MaterialPageRoute(
      builder: (_) => MyCastPage(
        controller: controller,
        supportedProtocols: event.supportedProtocols,
        mediaUrl: event.mediaUrl,
        title: event.title,
      ),
    ));
  }
});

// 投屏页 API
await controller.getSupportedCastProtocols();
await controller.getCastRequestContext();
await controller.refreshCastDevices();
await controller.getCastDevices();
final connectResult = await controller.connectCast(
  deviceId,
  url: castUrl, // 可选:投屏专用地址,与本机鉴权地址不同时传入
  title: '第 01 集',
  position: await controller.position,
);
final disconnectResult = await controller.disconnectCast();
await controller.stopCastDiscovery(); // 离开投屏页时停止发现
await controller.presentAirPlayPicker(); // iOS only

宿主配置 #

iOS Info.plist(本地网络与 Bonjour,用于 DLNA/Chromecast 发现):

<key>NSLocalNetworkUsageDescription</key>
<string>用于发现局域网投屏设备</string>
<key>NSBonjourServices</key>
<array>
  <string>_googlecast._tcp</string>
  <string>_upnp._tcp</string>
</array>
<key>NSAppTransportSecurity</key>
<dict>
  <key>NSAllowsLocalNetworking</key>
  <true/>
</dict>

iOS Chromecast:在 AppDelegate 中初始化 GCKCastContext(example 已配置)。

降级原生面板:设置 castUiMode: HmCastUiMode.native 可恢复内置原生投屏侧滑面板。

API 迁移 #

  • 推荐监听 CastRequestedEvent 替代仅依赖 ControlButtonTappedEvent(cast)
  • CastDevicesUpdatedEvent 在设备列表变化时推送。
  • CastStateChangedEvent 用于连接生命周期(discovering / connecting / connected / disconnected / failed)。
  • CastProgressEvent / CastPlayingChangedEvent 在投屏 connected 期间推送远端进度与播放状态(约 1 秒一次进度,状态变更时额外推送)。
  • 投屏控制方法(connectCast / disconnectCast / castPlay / castPause / castSeekTo / castSetMedia / castSetVolume)返回 CastCommandResult,建议同时监听 CastCommandResultEvent 获取最终命令执行结果。
1
likes
0
points
180
downloads

Publisher

unverified uploader

Weekly Downloads

跨平台视频播放器插件,支持全屏、画中画、投屏、倍速等功能。

Repository (GitHub)
View/report issues

Topics

#video-player #video #cast #picture-in-picture #fullscreen

License

unknown (license)

Dependencies

flutter

More

Packages that depend on hm_video_player

Packages that implement hm_video_player