@capgo/capacitor-video-player 8.1.24 → 8.1.25

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.
@@ -41,7 +41,7 @@ import java.util.Map;
41
41
  )
42
42
  public class VideoPlayerPlugin extends Plugin {
43
43
 
44
- private final String pluginVersion = "8.1.24";
44
+ private final String pluginVersion = "8.1.25";
45
45
 
46
46
  // Permission alias constants
47
47
  private static final String PERMISSION_DENIED_ERROR = "Unable to access media videos, user denied permission request";
@@ -1,5 +1,6 @@
1
1
  import AVFoundation
2
2
  import Foundation
3
+ import UniformTypeIdentifiers
3
4
 
4
5
  enum HLSVideoAssetFactory {
5
6
  static func isHLSStream(_ url: URL) -> Bool {
@@ -43,11 +44,17 @@ final class HLSSubtitleResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
43
44
  static let videoScheme = "capgohls"
44
45
  static let subtitlePlaylistScheme = "capgohls-sub"
45
46
  private static let subtitleGroupID = "capgosubs"
47
+ private static let mpegURLContentType = UTType.m3uPlaylist.identifier
46
48
 
47
49
  private let originalVideoURL: URL
48
50
  private let subtitleURL: URL
49
51
  private let language: String
50
52
 
53
+ private struct LoadedResource {
54
+ let data: Data
55
+ let contentType: String?
56
+ }
57
+
51
58
  init(videoURL: URL, subtitleURL: URL, language: String) {
52
59
  self.originalVideoURL = videoURL
53
60
  self.subtitleURL = subtitleURL
@@ -80,8 +87,8 @@ final class HLSSubtitleResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
80
87
 
81
88
  Task {
82
89
  do {
83
- let data = try await loadData(for: requestURL)
84
- fulfill(loadingRequest, with: data)
90
+ let resource = try await loadData(for: requestURL)
91
+ fulfill(loadingRequest, with: resource)
85
92
  } catch {
86
93
  loadingRequest.finishLoading(with: error)
87
94
  }
@@ -90,25 +97,36 @@ final class HLSSubtitleResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
90
97
  return true
91
98
  }
92
99
 
93
- private func loadData(for requestURL: URL) async throws -> Data {
100
+ private func loadData(for requestURL: URL) async throws -> LoadedResource {
94
101
  if requestURL.scheme == Self.subtitlePlaylistScheme {
95
- return Data(subtitleMediaPlaylist().utf8)
102
+ let data = Data(subtitleMediaPlaylist().utf8)
103
+ return LoadedResource(data: data, contentType: Self.mpegURLContentType)
96
104
  }
97
105
 
98
106
  let fetchURL = originalURL(for: requestURL)
99
- let (data, _) = try await URLSession.shared.data(from: fetchURL)
107
+ let (data, response) = try await URLSession.shared.data(from: fetchURL)
108
+ if let http = response as? HTTPURLResponse, !(200...299).contains(http.statusCode) {
109
+ throw URLError(.badServerResponse)
110
+ }
111
+
100
112
  let manifest = String(data: data, encoding: .utf8) ?? ""
101
113
 
102
114
  guard hasStreamInfTags(manifest) else {
103
- return data
115
+ let contentType = Self.contentTypeIdentifier(from: response)
116
+ return LoadedResource(data: data, contentType: contentType)
104
117
  }
105
118
 
106
119
  guard let subtitlePlaylistURI = Self.subtitlePlaylistURL(for: originalVideoURL)?.absoluteString else {
107
- return data
120
+ let contentType = Self.contentTypeIdentifier(from: response) ?? Self.mpegURLContentType
121
+ return LoadedResource(data: data, contentType: contentType)
108
122
  }
109
123
 
110
- let modified = injectSubtitle(into: manifest, subtitlePlaylistURI: subtitlePlaylistURI)
111
- return Data(modified.utf8)
124
+ let modified = injectSubtitle(
125
+ into: manifest,
126
+ subtitlePlaylistURI: subtitlePlaylistURI,
127
+ baseURL: response.url ?? fetchURL
128
+ )
129
+ return LoadedResource(data: Data(modified.utf8), contentType: Self.mpegURLContentType)
112
130
  }
113
131
 
114
132
  private func originalURL(for requestURL: URL) -> URL {
@@ -125,7 +143,22 @@ final class HLSSubtitleResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
125
143
  manifest.contains("#EXT-X-STREAM-INF")
126
144
  }
127
145
 
128
- private func injectSubtitle(into manifest: String, subtitlePlaylistURI: String) -> String {
146
+ private static func contentTypeIdentifier(from response: URLResponse) -> String? {
147
+ guard let mimeType = (response as? HTTPURLResponse)?.mimeType else {
148
+ return nil
149
+ }
150
+ return UTType(mimeType: mimeType)?.identifier
151
+ }
152
+
153
+ private func absoluteURI(for uri: String, relativeTo baseURL: URL) -> String {
154
+ let trimmed = uri.trimmingCharacters(in: .whitespacesAndNewlines)
155
+ guard let url = URL(string: trimmed, relativeTo: baseURL)?.absoluteURL else {
156
+ return trimmed
157
+ }
158
+ return url.absoluteString
159
+ }
160
+
161
+ private func injectSubtitle(into manifest: String, subtitlePlaylistURI: String, baseURL: URL) -> String {
129
162
  let mediaTag = """
130
163
  #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="\(Self.subtitleGroupID)",NAME="Subtitles",DEFAULT=YES,AUTOSELECT=YES,FORCED=NO,LANGUAGE="\(language)",URI="\(subtitlePlaylistURI)"
131
164
  """
@@ -133,9 +166,10 @@ final class HLSSubtitleResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
133
166
  var lines = manifest.components(separatedBy: .newlines)
134
167
  var result: [String] = []
135
168
  var insertedMediaTag = false
169
+ var expectingVariantURI = false
136
170
 
137
171
  for line in lines {
138
- if line.hasPrefix("#EXT-X-STREAM-INF") {
172
+ if line.hasPrefix("#EXT-X-STREAM-INF") || line.hasPrefix("#EXT-X-I-FRAME-STREAM-INF") {
139
173
  if !insertedMediaTag {
140
174
  result.append(mediaTag)
141
175
  insertedMediaTag = true
@@ -146,9 +180,17 @@ final class HLSSubtitleResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
146
180
  } else {
147
181
  result.append("\(line),SUBTITLES=\"\(Self.subtitleGroupID)\"")
148
182
  }
183
+ expectingVariantURI = true
149
184
  continue
150
185
  }
151
186
 
187
+ if expectingVariantURI, !line.hasPrefix("#"), !line.isEmpty {
188
+ result.append(absoluteURI(for: line, relativeTo: baseURL))
189
+ expectingVariantURI = false
190
+ continue
191
+ }
192
+
193
+ expectingVariantURI = false
152
194
  result.append(line)
153
195
  }
154
196
 
@@ -172,14 +214,16 @@ final class HLSSubtitleResourceLoader: NSObject, AVAssetResourceLoaderDelegate {
172
214
  """
173
215
  }
174
216
 
175
- private func fulfill(_ loadingRequest: AVAssetResourceLoadingRequest, with data: Data) {
217
+ private func fulfill(_ loadingRequest: AVAssetResourceLoadingRequest, with resource: LoadedResource) {
176
218
  if let contentRequest = loadingRequest.contentInformationRequest {
177
- contentRequest.contentType = "application/vnd.apple.mpegurl"
178
- contentRequest.contentLength = Int64(data.count)
219
+ if let contentType = resource.contentType {
220
+ contentRequest.contentType = contentType
221
+ }
222
+ contentRequest.contentLength = Int64(resource.data.count)
179
223
  contentRequest.isByteRangeAccessSupported = false
180
224
  }
181
225
 
182
- loadingRequest.dataRequest?.respond(with: data)
226
+ loadingRequest.dataRequest?.respond(with: resource.data)
183
227
  loadingRequest.finishLoading()
184
228
  }
185
229
  }
@@ -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.1.24"
11
+ private let pluginVersion: String = "8.1.25"
12
12
  public let identifier = "VideoPlayerPlugin"
13
13
  public let jsName = "VideoPlayer"
14
14
  public let pluginMethods: [CAPPluginMethod] = [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capgo/capacitor-video-player",
3
- "version": "8.1.24",
3
+ "version": "8.1.25",
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",