@capgo/capacitor-video-player 8.2.2 → 8.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -46,7 +46,7 @@ import org.json.JSONObject;
46
46
  )
47
47
  public class VideoPlayerPlugin extends Plugin {
48
48
 
49
- private final String pluginVersion = "8.2.2";
49
+ private final String pluginVersion = "8.2.3";
50
50
 
51
51
  // Permission alias constants
52
52
  private static final String PERMISSION_DENIED_ERROR = "Unable to access media videos, user denied permission request";
@@ -81,7 +81,7 @@ class FullscreenVideoPlayer: NSObject {
81
81
  }
82
82
 
83
83
  func setupPlayer(completion: @escaping () -> Void) {
84
- guard let url = URL(string: videoUrl) else {
84
+ guard let url = Self.resolveMediaURL(videoUrl) else {
85
85
  completion()
86
86
  return
87
87
  }
@@ -100,8 +100,9 @@ class FullscreenVideoPlayer: NSObject {
100
100
  return
101
101
  }
102
102
 
103
- // Prefer the resource-loader path for any video with sidecar subtitles.
104
- // That exposes selectable tracks in AVPlayerViewController (composition does not).
103
+ // Prefer the resource-loader path when makeAsset can safely wrap the stream
104
+ // (HLS / remote progressive). Local progressive file:// sources return a nil
105
+ // loader and must use composition so playback still starts (#78).
105
106
  let assetResult = HLSVideoAssetFactory.makeAsset(
106
107
  videoURL: url,
107
108
  subtitleTracks: subtitleTracks
@@ -127,6 +128,17 @@ class FullscreenVideoPlayer: NSObject {
127
128
  }
128
129
  }
129
130
 
131
+ private static func resolveMediaURL(_ raw: String) -> URL? {
132
+ guard !raw.isEmpty else { return nil }
133
+ if let parsed = URL(string: raw), parsed.scheme != nil {
134
+ return parsed
135
+ }
136
+ if raw.hasPrefix("/") {
137
+ return URL(fileURLWithPath: raw)
138
+ }
139
+ return URL(string: raw)
140
+ }
141
+
130
142
  private func makeVideoAsset(url: URL, subtitleTracks: [VideoSubtitleTrack]) -> AVURLAsset {
131
143
  let result = HLSVideoAssetFactory.makeAsset(
132
144
  videoURL: url,
@@ -32,6 +32,14 @@ enum HLSVideoAssetFactory {
32
32
  return (AVURLAsset(url: videoURL), nil)
33
33
  }
34
34
 
35
+ // Local progressive files cannot be wrapped in synthetic HLS playlists:
36
+ // AVPlayer will not fetch file:// media/subtitle segments from a custom-scheme
37
+ // master playlist, so playback never becomes ready (#78). Fall back to the
38
+ // composition path in FullscreenVideoPlayer instead.
39
+ if videoURL.isFileURL && !isHLSStream(videoURL) {
40
+ return (AVURLAsset(url: videoURL), nil)
41
+ }
42
+
35
43
  let resourceLoader = HLSSubtitleResourceLoader(
36
44
  videoURL: videoURL,
37
45
  subtitleTracks: resolvedTracks.map { HLSSubtitleTrack(url: $0.url, language: $0.language) },
@@ -8,7 +8,7 @@ import AVKit
8
8
  */
9
9
  @objc(VideoPlayerPlugin)
10
10
  public class VideoPlayerPlugin: CAPPlugin, CAPBridgedPlugin {
11
- private let pluginVersion: String = "8.2.2"
11
+ private let pluginVersion: String = "8.2.3"
12
12
  public let identifier = "VideoPlayerPlugin"
13
13
  public let jsName = "VideoPlayer"
14
14
  public let pluginMethods: [CAPPluginMethod] = [
@@ -6,6 +6,13 @@ struct VideoSubtitleTrack {
6
6
 
7
7
  var resolvedURL: URL? {
8
8
  guard !url.isEmpty else { return nil }
9
+ if let parsed = URL(string: url), parsed.scheme != nil {
10
+ return parsed
11
+ }
12
+ // Capacitor filesystem paths sometimes arrive without a file:// scheme.
13
+ if url.hasPrefix("/") {
14
+ return URL(fileURLWithPath: url)
15
+ }
9
16
  return URL(string: url)
10
17
  }
11
18
  }
@@ -62,4 +62,30 @@ final class HLSSubtitlePlaylistTests: XCTestCase {
62
62
  XCTAssertNil(result.resourceLoader)
63
63
  XCTAssertEqual(result.asset.url, videoURL)
64
64
  }
65
+
66
+ func testMakeAssetSkipsResourceLoaderForLocalProgressiveSubtitles() {
67
+ let videoURL = URL(fileURLWithPath: "/var/mobile/Containers/Data/Application/video.mp4")
68
+ let tracks = [
69
+ VideoSubtitleTrack(url: "file:///var/mobile/Containers/Data/Application/subtitles-en.vtt", language: "en"),
70
+ VideoSubtitleTrack(url: "file:///var/mobile/Containers/Data/Application/subtitles-fr.vtt", language: "fr")
71
+ ]
72
+
73
+ let result = HLSVideoAssetFactory.makeAsset(videoURL: videoURL, subtitleTracks: tracks)
74
+
75
+ XCTAssertNil(result.resourceLoader)
76
+ XCTAssertEqual(result.asset.url, videoURL)
77
+ XCTAssertEqual(result.asset.url.scheme, "file")
78
+ }
79
+
80
+ func testMakeAssetUsesResourceLoaderForLocalHLSSubtitles() {
81
+ let videoURL = URL(fileURLWithPath: "/var/mobile/Containers/Data/Application/stream.m3u8")
82
+ let tracks = [
83
+ VideoSubtitleTrack(url: "file:///var/mobile/Containers/Data/Application/subtitles-en.vtt", language: "en")
84
+ ]
85
+
86
+ let result = HLSVideoAssetFactory.makeAsset(videoURL: videoURL, subtitleTracks: tracks)
87
+
88
+ XCTAssertNotNil(result.resourceLoader)
89
+ XCTAssertEqual(result.asset.url.scheme, HLSSubtitleResourceLoader.videoScheme)
90
+ }
65
91
  }
@@ -24,4 +24,10 @@ class VideoPlayerTests: XCTestCase {
24
24
  XCTAssertEqual(tracks[0].language, "en")
25
25
  XCTAssertEqual(tracks[1].language, "fr")
26
26
  }
27
+
28
+ func testSubtitleTrackResolvesBareFilePath() {
29
+ let track = VideoSubtitleTrack(url: "/var/mobile/Containers/Data/Application/subtitles-en.vtt", language: "en")
30
+ XCTAssertEqual(track.resolvedURL?.isFileURL, true)
31
+ XCTAssertEqual(track.resolvedURL?.path, "/var/mobile/Containers/Data/Application/subtitles-en.vtt")
32
+ }
27
33
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-video-player",
3
- "version": "8.2.2",
3
+ "version": "8.2.3",
4
4
  "description": "Capacitor plugin to play video in native player",
5
5
  "main": "dist/plugin.cjs.js",
6
6
  "module": "dist/esm/index.js",