feat: implement startPosition (#3355)

* feat(android): implement startPosition

* feat(ios): implement startPosition

* feat: implement startPosition type

* docs: fix typo

* docs: update startPosition

* refactor: put startPosition inside source prop
- put startPosition inside source prop
- rename existing prop (startTime, endTime)

* docs: update startPosition property description

* fix: fix invalid assignments

* refactor: remove redundant optional chaining

* feat: allow "0" to work too
This commit is contained in:
YangJH
2023-11-24 20:52:46 +09:00
committed by GitHub
parent 0c0f3174cb
commit 2648502b36
9 changed files with 86 additions and 47 deletions

View File

@@ -6,8 +6,9 @@ struct VideoSource {
let isAsset: Bool
let shouldCache: Bool
let requestHeaders: Dictionary<String,Any>?
let startTime: Int64?
let endTime: Int64?
let startPosition: Int64?
let cropStart: Int64?
let cropEnd: Int64?
// Custom Metadata
let title: String?
let subtitle: String?
@@ -25,8 +26,9 @@ struct VideoSource {
self.isAsset = false
self.shouldCache = false
self.requestHeaders = nil
self.startTime = nil
self.endTime = nil
self.startPosition = nil
self.cropStart = nil
self.cropEnd = nil
self.title = nil
self.subtitle = nil
self.description = nil
@@ -40,8 +42,9 @@ struct VideoSource {
self.isAsset = json["isAsset"] as? Bool ?? false
self.shouldCache = json["shouldCache"] as? Bool ?? false
self.requestHeaders = json["requestHeaders"] as? Dictionary<String,Any>
self.startTime = json["startTime"] as? Int64
self.endTime = json["endTime"] as? Int64
self.startPosition = json["startPosition"] as? Int64
self.cropStart = json["cropStart"] as? Int64
self.cropEnd = json["cropEnd"] as? Int64
self.title = json["title"] as? String
self.subtitle = json["subtitle"] as? String
self.description = json["description"] as? String

View File

@@ -19,8 +19,8 @@ enum RCTVideoUtils {
return 0
}
if (source?.startTime != nil && source?.endTime != nil) {
return NSNumber(value: (Float64(source?.endTime ?? 0) - Float64(source?.startTime ?? 0)) / 1000)
if (source?.cropStart != nil && source?.cropEnd != nil) {
return NSNumber(value: (Float64(source?.cropEnd ?? 0) - Float64(source?.cropStart ?? 0)) / 1000)
}
var effectiveTimeRange:CMTimeRange?
@@ -35,8 +35,8 @@ enum RCTVideoUtils {
if let effectiveTimeRange = effectiveTimeRange {
let playableDuration:Float64 = CMTimeGetSeconds(CMTimeRangeGetEnd(effectiveTimeRange))
if playableDuration > 0 {
if (source?.startTime != nil) {
return NSNumber(value: (playableDuration - Float64(source?.startTime ?? 0) / 1000))
if (source?.cropStart != nil) {
return NSNumber(value: (playableDuration - Float64(source?.cropStart ?? 0) / 1000))
}
return playableDuration as NSNumber

View File

@@ -66,6 +66,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
private var _filterEnabled:Bool = false
private var _presentingViewController:UIViewController?
private var _pictureInPictureEnabled = false
private var _startPosition:Float64 = -1
/* IMA Ads */
private var _adTagUrl:String?
@@ -251,8 +252,8 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
}
var currentTime = _player?.currentTime()
if (currentTime != nil && _source?.startTime != nil) {
currentTime = CMTimeSubtract(currentTime!, CMTimeMake(value: _source?.startTime ?? 0, timescale: 1000))
if (currentTime != nil && _source?.cropStart != nil) {
currentTime = CMTimeSubtract(currentTime!, CMTimeMake(value: _source?.cropStart ?? 0, timescale: 1000))
}
let currentPlaybackTime = _player?.currentItem?.currentDate()
let duration = CMTimeGetSeconds(playerDuration)
@@ -316,6 +317,10 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
throw NSError(domain: "", code: 0, userInfo: nil)
}
if let startPosition = self._source?.startPosition {
self._startPosition = Float64(startPosition) / 1000
}
#if USE_VIDEO_CACHING
if self._videoCache.shouldCache(source:source, textTracks:self._textTracks) {
return self._videoCache.playerItemForSourceUsingCache(uri: source.uri, assetOptions:assetOptions)
@@ -341,7 +346,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
self._playerItem = playerItem
self._playerObserver.playerItem = self._playerItem
self.setPreferredForwardBufferDuration(self._preferredForwardBufferDuration)
self.setPlaybackRange(playerItem, withVideoStart: self._source?.startTime, withVideoEnd: self._source?.endTime)
self.setPlaybackRange(playerItem, withVideoStart: self._source?.cropStart, withVideoEnd: self._source?.cropEnd)
self.setFilter(self._filterName)
if let maxBitRate = self._maxBitRate {
self._playerItem?.preferredPeakBitRate = Double(maxBitRate)
@@ -601,6 +606,7 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
_pendingSeek = false
}
@objc
func setRate(_ rate:Float) {
_rate = rate
@@ -1177,6 +1183,14 @@ class RCTVideo: UIView, RCTVideoPlayerViewControllerDelegate, RCTPlayerObserverH
_pendingSeek = false
}
if _startPosition >= 0 {
setSeek([
"time": NSNumber(value: _startPosition),
"tolerance": NSNumber(value: 100)
])
_startPosition = -1
}
if _videoLoadStarted {
let audioTracks = RCTVideoUtils.getAudioTrackInfo(_player)
let textTracks = RCTVideoUtils.getTextTrackInfo(_player).map(\.json)