2
votes

AVPlayer Seek n'est pas précis, même avec la tolérance Avant: kCMTimeZero

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 devons utiliser AVPlayer car nous avons besoin de la meilleure qualité "spectral:" AVAudioTimePitchAlgorithm.
  • 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:]

  • Nous avons déjà essayé preferTimescale: playerTimescale
  • J'ai également essayé kCMTimeIndefinite au lieu de kCMTimeZero


3 commentaires

Cela ressemble à un travail pour AVURLAssetPreferPreciseDurationAndTimingKey d'AVURLAsset

3 Réponses :


2
votes

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
            })
        }
    }


1 commentaires

Merci Enea, nous avons essayé mais cela n'a pas aidé, merci pour la suggestion cependant.



0
votes

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()
        }
    }
}


1 commentaires

Merci Naveen, nous avons essayé cela mais à la fin c'était l'AVURLAssetPreferPreciseDurationAndTimingKey. Mais appréciez votre suggestion.