SWIFT - MP4セグメントまたはマージセグメントをMP4に再生するためのM3U8に代わるもの -- ios フィールド と swift フィールド と ffmpeg フィールド と avplayer フィールド と m3u8 フィールド 関連 問題

Swift - Workaround/Alternative to M3u8 to play mp4 segment or merge segments into mp4












0
vote

問題

日本語

avassetexportSession セッションのURLをダウンロードするには、ライブストリームをダウンロードすることができないという問題があるため、ライブストリームは10秒間のMP4セグメントに分割されています。 URLを作成するためのM3U8。その後、 avassetexportsession を使用してそれらのMP4セグメントをマージします。

これらのクリップを1つずつマージすることができますが、ファイルが大きくなるにつれて、予防的になる数千のセグメントに対処するにつれて時間がかかります。

AvplayerLooper を使用することについて考えましたが、単一のビデオのようなMP4セグメントを介してスクラブ、巻き戻し、転送することはできません。

M3U8がマージされずにM3U8のビデオとして再生するためにMP4クリップを組み合わせる方法はありますか?またはビデオをマージする速い方法はありますか?

:サーバーはffmpegを使用していますが、アプリ内のFFMPEGやポッドを使用することはできません。

はビデオをマージする機能です

<事前> <コード> var mp4Array: [AVAsset] = [] var avAssetExportSession: AVAssetExportSession? var firstAsset: AVAsset? var secondAsset: AVAsset? func mergeVideos() { firstAsset = mp4Array.first secondAsset = mp4Array[1] guard let firstAsset = firstAsset, let secondAsset = secondAsset else { return } let mixComposition = AVMutableComposition() guard let firstTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else {return} do { try firstTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: firstAsset.duration), of: firstAsset.tracks(withMediaType: .video)[0], at: CMTime.zero) } catch { print("Couldn't load track 1") return } guard let secondTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else {return} do { try secondTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: secondAsset.duration), of: secondAsset.tracks(withMediaType: .video)[0], at: firstAsset.duration) } catch { print("couldn't load track 2") return } let mainInstruction = AVMutableVideoCompositionInstruction() mainInstruction.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: CMTimeAdd(firstAsset.duration, secondAsset.duration)) let firstAssetInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: firstTrack) firstAssetInstruction.setOpacity(0.0, at: firstAsset.duration) let secondAssetInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: secondTrack) mainInstruction.layerInstructions = [firstAssetInstruction, secondAssetInstruction] let mainComposition = AVMutableVideoComposition() mainComposition.instructions = [mainInstruction] mainComposition.frameDuration = CMTimeMake(value: 1, timescale: 30) mainComposition.renderSize = firstTrack.naturalSize guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return } let url = documentDirectory.appendingPathComponent("MergedVideos/mergeVideo(videoInt).mp4") guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else {return} exporter.outputURL = url exporter.outputFileType = AVFileType.mp4 exporter.shouldOptimizeForNetworkUse = true exporter.videoComposition = mainComposition exporter.exportAsynchronously { if exporter.status == .completed { let avasset = AVAsset(url:url) self.mergeUrl = avasset if self.mp4Array.count > 1{ print("This add the merged video to the front of the mp4array") self.mp4Array.remove(at: 1) self.mp4Array.removeFirst() self.videoInt = self.videoInt + 1 self.mp4Array.append(self.mergeUrl!) self.mp4Array.bringToFront(item: self.mp4Array.last!) } if (self.mp4Array.count > 1){ if self.mergeUrl != nil { self.mergeVideos() } } else { var numberofvideosdeleted = 0 while (numberofvideosdeleted < self.videoInt - 1){ do { print("deleting") let url = documentDirectory.appendingPathComponent("MergedVideos/mergeVideo(numberofvideosdeleted).mp4") try FileManager.default.removeItem(at: url) numberofvideosdeleted = numberofvideosdeleted + 1 } catch { print("Error removing videos") } } self.deleteCurrentSegementsInFolder() } } } }
英語

I used AVAssetExportSession to download a session URL but the issue that you can't download live stream so to get around it, the live stream is split into 10 seconds mp4 segments that are downloaded using an m3u8 to create the URLs. I then use AVAssetExportSession to merge those mp4 segments.

I can merge those clips one by one into one mp4 file which is what I want but as the file gets bigger, the longer it takes as I am dealing with thousands of segments which becomes unpractical.

I thought about using AVplayerLooper but I cannot scrub, rewind or forward through the mp4 segment like a single video.

Is there a way to combine the mp4 clips together to play as one video as the m3u8 does without merging? or is there a fast way to merge videos?

Note: The server uses FFmpeg but I am not allowed to use FFmpeg or pods in the app.

below is the function to merge videos

var mp4Array: [AVAsset] = [] var avAssetExportSession: AVAssetExportSession?  var firstAsset: AVAsset? var secondAsset: AVAsset?  func mergeVideos() {      firstAsset = mp4Array.first     secondAsset = mp4Array[1]      guard let firstAsset = firstAsset, let secondAsset = secondAsset else { return }     let mixComposition = AVMutableComposition()      guard let firstTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else {return}      do {          try firstTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: firstAsset.duration),                                        of: firstAsset.tracks(withMediaType: .video)[0],                                        at: CMTime.zero)      } catch {         print("Couldn't load track 1")         return     }      guard let secondTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else {return}      do {         try secondTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: secondAsset.duration),                                         of: secondAsset.tracks(withMediaType: .video)[0],                                         at: firstAsset.duration)     } catch {         print("couldn't load track 2")         return     }      let mainInstruction = AVMutableVideoCompositionInstruction()     mainInstruction.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: CMTimeAdd(firstAsset.duration, secondAsset.duration))      let firstAssetInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: firstTrack)     firstAssetInstruction.setOpacity(0.0, at: firstAsset.duration)      let secondAssetInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: secondTrack)      mainInstruction.layerInstructions = [firstAssetInstruction, secondAssetInstruction]     let mainComposition = AVMutableVideoComposition()     mainComposition.instructions = [mainInstruction]     mainComposition.frameDuration = CMTimeMake(value: 1, timescale: 30)     mainComposition.renderSize = firstTrack.naturalSize      guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }     let url = documentDirectory.appendingPathComponent("MergedVideos/mergeVideo(videoInt).mp4")      guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else {return}      exporter.outputURL = url     exporter.outputFileType = AVFileType.mp4     exporter.shouldOptimizeForNetworkUse = true     exporter.videoComposition = mainComposition      exporter.exportAsynchronously {          if exporter.status == .completed {             let avasset = AVAsset(url:url)             self.mergeUrl = avasset             if self.mp4Array.count > 1{                 print("This add the merged video to the front of the mp4array")                 self.mp4Array.remove(at: 1)                 self.mp4Array.removeFirst()                 self.videoInt = self.videoInt + 1                 self.mp4Array.append(self.mergeUrl!)                 self.mp4Array.bringToFront(item: self.mp4Array.last!)             }              if (self.mp4Array.count > 1){                 if self.mergeUrl != nil {                     self.mergeVideos()                 }             } else {                 var numberofvideosdeleted = 0                 while (numberofvideosdeleted < self.videoInt - 1){                     do {                         print("deleting")                         let url = documentDirectory.appendingPathComponent("MergedVideos/mergeVideo(numberofvideosdeleted).mp4")                         try FileManager.default.removeItem(at: url)                         numberofvideosdeleted = numberofvideosdeleted + 1                     } catch {                         print("Error removing videos")                     }                 }                  self.deleteCurrentSegementsInFolder()             }         }     } } 
</div
              

回答リスト

1
 
vote
vote
ベストアンサー
 

FFMPEG Mobileを使ってビデオを連結し、本当にうまく機能しています。 3GBムービーファイルを連結するには約1分かかります。

CocoApodへの下のリンク: https://github.com/tanersener/mobile-ffmpeg

 

I ended up using FFmpeg Mobile to concatenate the videos and it works really well. Takes around 1 minute to concatenate a 3GB movie file.

Link below to the cocoapod: https://github.com/tanersener/mobile-ffmpeg

</div
 
 

関連する質問

1  JWPlayerを使ってビデオファイルが再生されません  ( Video file wont play using jwplayer ) 
私は専門家ではない、私は盲目の模倣をしています 私はM3U8ファイルを作成して記憶しました これはそれがを含むものです <コード> #EXTM3U #EXT-X-VERSION:6 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-...

0  Streaming M3U8 HLS Androidのオーディオ  ( Streaming m3u8 hls audio on android ) 
Android上でM3U8 HLSオーディオストリーミングを再現しようとする問題を見つけました。今すぐM3U8 HLSリンクでビデオを再現できます。 <事前> <コード> Intent i = new Intent(Intent.ACTION_VIEW); ...

1  ビデオはUWPの復号します  ( Video decoding in uwp ) 
私は.m3u8ファイルを再生できるアプリケーションを持っています。 しかし、ビデオの MPEG 1/2 (mpgv) は、それが唯一のショーの空白の画面でエンコードされたとき。 <コード> H.264 のようなビデオを開くと、すべてがOKです。何が問題なのです...

0  Safari / iOSはHTTPライブストリームの自動再生をサポートしていますか?  ( Does safari ios support autoplay of http live streams ) 
私はHLS全体、M3U8と自動再生のための初心者です。 iOSは、ユーザーのジェスチャーなしでオーディオを使用してHTTPライブストリーミングの自動再生をサポートしていますか? もしそうなら、iOS上のSafariにロードできるサンプルWebページはあります...

1  JavaFX MediaPlayerローカルM3U8ファイルを再生できません  ( Javafx mediaplayer unable to play local m3u8 file ) 
MediaPlayer / MediaViewを使用して、JavaFXアプリケーションでWeb CAMのライブストリームを表示したいです。私の試みは、FFMPEGを使用してHLSを記録し、結果のM3U8ファイルを再生しますが、次の例外をスローします(VLCは...

-1  M3U8プレイリストを解析して、.tsチャンクのURLを取得できますか?  ( How can i parse m3u8 playlist to retrieve the url of ts chunks ) 
これは<コード> m3u8 リンクURL:です。 <事前> <コード> https://thr-pltv-4.aionet.ir/hls.m3u8?mwk=89374692478207427715317283451977223330&s=59560951766...

0  JS Reload(Python)の後にネットワークストリームからM3U8を削除する方法  ( How to scrape m3u8 from network stream after a js reload python ) 
beautifulsoup および<コード>および<コード> 99887663 を使用してPythonプログラムを実行して、埋め込みビデオURLを削除しますが、ADSポップアップと<コード> javascript <を迂回する必要があります。 / CODE...

0  Apple App Storeによる承認に必要なFFMPEG HLS出力設定  ( Ffmpeg hls output settings required for approval by the apple app store ) 
私は全面的に見えましたが、私はこれまでの質問に対する直接の答えを見つけていません。 最小必要なFFMPEGコマンドライン出力とセグメンテーション設定とは何ですか。 注意:古いQ&AMPがあります。ここでは、FFMPEGがHLSのネイティブセグメンテーションを...

0  HTML5ビデオタグがAndroidで動作していません  ( Html5 video tag currenttime not working in android ) 
私はHTML5ビデオタグを使用しています、私はソースのための.m3u8ファイルを使用しています。 Android 4以降のCurrentTimeプロパティを使用してビデオをシークすることはできませんが、.mp4ファイルを使用できます。 iPadでは正しく機...

0  単一のファイルがHLS M3U8プレイリストから存在しない場合は、プレイヤーが停止します。  ( Player stops if even a single file does not exist from hls m3u8 playlist ) 
ビッグM3U8プレイリストを持っているとします <事前> <コード> #EXTM3U #EXT-X-VERSION:3 #EXT-X-MEDIA-SEQUENCE:0 #EXT-X-TARGETDURATION:10 #EXT-X-DISCONTINUITY ...




© 2022 cndgn.com All Rights Reserved. Q&Aハウス 全著作権所有