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