fix(ios): fix sideloading external subtitles (#3690)

* fix(ios): fix subtitles side loading

* update example

* Update examples/basic/src/VideoPlayer.tsx

Co-authored-by: Olivier Bouillet <62574056+freeboub@users.noreply.github.com>

* Update examples/basic/src/VideoPlayer.tsx

Co-authored-by: Olivier Bouillet <62574056+freeboub@users.noreply.github.com>

---------

Co-authored-by: Olivier Bouillet <62574056+freeboub@users.noreply.github.com>
This commit is contained in:
Krzysztof Moch 2024-04-19 22:38:52 +02:00 committed by GitHub
parent b5ccc48476
commit efa1c52491
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 20 additions and 21 deletions

View File

@ -134,8 +134,10 @@ class VideoPlayer extends Component {
uri: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8', uri: 'https://bitmovin-a.akamaihd.net/content/sintel/hls/playlist.m3u8',
}, },
{ {
description: 'sintel with sideLoaded subtitles', description: 'BigBugBunny sideLoaded subtitles',
uri: 'https://demo.unified-streaming.com/k8s/features/stable/video/tears-of-steel/tears-of-steel.ism/.m3u8', // this is sample video, my actual video file is MP4 // sideloaded subtitles wont work for streaming like HLS on ios
// mp4
uri: 'https://d23dyxeqlo5psv.cloudfront.net/big_buck_bunny.mp4',
textTracks: [ textTracks: [
{ {
title: 'test', title: 'test',
@ -195,7 +197,7 @@ class VideoPlayer extends Component {
description: 'rtsp big bug bunny', description: 'rtsp big bug bunny',
uri: 'rtsp://rtspstream:3cfa3c36a9c00f4aa38f3cd35816b287@zephyr.rtsp.stream/movie', uri: 'rtsp://rtspstream:3cfa3c36a9c00f4aa38f3cd35816b287@zephyr.rtsp.stream/movie',
type: 'rtsp', type: 'rtsp',
} },
]; ];
// poster which can be displayed // poster which can be displayed
@ -240,20 +242,20 @@ class VideoPlayer extends Component {
setTimeout(() => { setTimeout(() => {
const position = this.calculateSeekerPosition(); const position = this.calculateSeekerPosition();
this.setSeekerPosition(position); this.setSeekerPosition(position);
}, 1) }, 1);
} };
onProgress = (data: OnProgressData) => { onProgress = (data: OnProgressData) => {
this.setState({currentTime: data.currentTime}); this.setState({currentTime: data.currentTime});
if (!this.state.seeking) { if (!this.state.seeking) {
this.updateSeeker() this.updateSeeker();
} }
}; };
onSeek = (data: OnSeekData) => { onSeek = (data: OnSeekData) => {
this.setState({currentTime: data.currentTime}); this.setState({currentTime: data.currentTime});
this.updateSeeker() this.updateSeeker();
} };
onVideoLoadStart = () => { onVideoLoadStart = () => {
console.log('onVideoLoadStart'); console.log('onVideoLoadStart');
@ -363,11 +365,11 @@ class VideoPlayer extends Component {
onPlaybackRateChange = (data: OnPlaybackRateChangeData) => { onPlaybackRateChange = (data: OnPlaybackRateChangeData) => {
console.log('onPlaybackRateChange', data); console.log('onPlaybackRateChange', data);
} };
onPlaybackStateChanged = (data: OnPlaybackStateChangedData) => { onPlaybackStateChanged = (data: OnPlaybackStateChangedData) => {
console.log('onPlaybackStateChanged', data); console.log('onPlaybackStateChanged', data);
} };
toggleFullscreen() { toggleFullscreen() {
this.setState({fullscreen: !this.state.fullscreen}); this.setState({fullscreen: !this.state.fullscreen});

View File

@ -246,7 +246,7 @@ enum RCTVideoUtils {
static func getValidTextTracks(asset: AVAsset, assetOptions: NSDictionary?, mixComposition: AVMutableComposition, static func getValidTextTracks(asset: AVAsset, assetOptions: NSDictionary?, mixComposition: AVMutableComposition,
textTracks: [TextTrack]?) async -> [TextTrack] { textTracks: [TextTrack]?) async -> [TextTrack] {
var validTextTracks: [TextTrack] = [] var validTextTracks: [TextTrack] = []
var tracks: [[AVAssetTrack]] = [] var tracks: [([AVAssetTrack], AVURLAsset)] = []
let videoTracks = await RCTVideoAssetsUtils.getTracks(asset: asset, withMediaType: .video) let videoTracks = await RCTVideoAssetsUtils.getTracks(asset: asset, withMediaType: .video)
guard let videoAsset = videoTracks?.first else { return validTextTracks } guard let videoAsset = videoTracks?.first else { return validTextTracks }
@ -268,23 +268,20 @@ enum RCTVideoUtils {
} }
if let track = await RCTVideoAssetsUtils.getTracks(asset: textURLAsset, withMediaType: .text) { if let track = await RCTVideoAssetsUtils.getTracks(asset: textURLAsset, withMediaType: .text) {
tracks.append(track) tracks.append((track, textURLAsset))
} }
} }
for i in 0 ..< tracks.count { for (index, tracksPair) in tracks.enumerated() {
guard let track = tracks[i].first else { continue } // fix when there's no textTrackAsset let (tracks, trackAsset) = tracksPair
guard let track = tracks.first else { continue } // fix when there's no textTrackAsset
let textCompTrack: AVMutableCompositionTrack! = mixComposition.addMutableTrack(withMediaType: AVMediaType.text, let textCompTrack: AVMutableCompositionTrack! = mixComposition.addMutableTrack(withMediaType: AVMediaType.text,
preferredTrackID: kCMPersistentTrackID_Invalid) preferredTrackID: kCMPersistentTrackID_Invalid)
do { do {
try textCompTrack.insertTimeRange( try textCompTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: trackAsset.duration), of: track, at: .zero)
CMTimeRangeMake(start: .zero, duration: videoAsset.timeRange.duration), validTextTracks.append(textTracks[index])
of: track,
at: .zero
)
validTextTracks.append(textTracks[i])
} catch { } catch {
// TODO: upgrade error by call some props callback to better inform user // TODO: upgrade error by call some props callback to better inform user
print("Error occurred on textTrack insert attempt: \(error.localizedDescription)") print("Error occurred on textTrack insert attempt: \(error.localizedDescription)")