Nous avons une application qui lit un long fichier mp3 (1 heure). Nous voulons pouvoir jouer à partir de points de consigne dans le fichier. Mais, lorsque nous le faisons, il est inexact jusqu'à 10 secondes.
Voici le code:
let trackStart = arrTracks![MediaPlayer.shared.currentSongNo].samples let frameRate : Int32 = (MediaPlayer.shared.player?.currentItem?.asset.duration.timescale)! MediaPlayer.shared.player?.seek(to: CMTimeMakeWithSeconds(Double(trackStart), frameRate), toleranceBefore: kCMTimeZero, toleranceAfter: kCMTimeZero)
Nous n'avons pas eu de problème avec AVAudioPlayer, mais (AFAIK) nous devons utiliser AVPlayer car nous avons besoin de la meilleure qualité "spectral:" AVAudioTimePitchAlgorithm.
[Edit:] - L'erreur est cohérente - elle joue toujours du même (mauvais) endroit pour une position demandée donnée. Cela est également vrai après le redémarrage.
Toute aide très appréciée! Merci
[Modifier:]
preferTimescale: playerTimescale
kCMTimeIndefinite
au lieu de kCMTimeZero
3 Réponses :
J'ai fait quelque chose de similaire mais avec un curseur pour changer les secondes de lecture et j'ai parfaitement fonctionné.
let trackStart = arrTracks![MediaPlayer.shared.currentSongNo].samples let value = Float64(trackStart) let seekTime = CMTime(value: CMTimeValue(value), timescale: 1) MediaPlayer.shared.player?.seek(to: seekTime , completionHandler: { (completedSeek) in //do smthg later })
dans votre cas, ce sera comme ceci:
@objc func handleSliderChange(sender: UISlider?){ if let duration = player?.currentItem?.duration{ let totalSeconds = CMTimeGetSeconds(duration) let value = Float64(videoSlider.value) * totalSeconds let seekTime = CMTime(value: CMTimeValue(value), timescale: 1) player?.seek(to: seekTime , completionHandler: { (completedSeek) in //do smthg later }) } }
Merci Enea, nous avons essayé mais cela n'a pas aidé, merci pour la suggestion cependant.
Essayez ceci, cela fonctionne parfaitement pour moi
@IBAction func playbackSliderValueChanged(_ playbackSlider: UISlider) { let seconds : Int64 = Int64(playbackSlider.value) let targetTime: CMTime = CMTimeMake(value: seconds, timescale: 1) DispatchQueue.main.async { self.player!.seek(to: targetTime) if self.player!.rate == 0 { // if the player is not yet started playing self.player?.play() } } }
Merci Naveen, nous avons essayé cela mais à la fin c'était l'AVURLAssetPreferPreciseDurationAndTimingKey. Mais appréciez votre suggestion.
C'est à cela que sert AVURLAsset
AVURLAssetPreferPreciseDurationAndTimingKey
.
Attention, cela devrait augmenter le temps de chargement.
Cela ressemble à un travail pour AVURLAssetPreferPreciseDurationAndTimingKey d'AVURLAsset