antonyraphel / ARStories

It is similar like Instagram Stories, to show video or photo directly of the users account.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Timer is running without sync with video duration and image

Durga-Veerendra opened this issue · comments

Timer is running without sync with video duration and image. If an image or video still under downloading from the network, the top status is running and moved to next image or video.
please help me in this.

I have the same issue. Please provide a solution if available.
Thank you

Hi, i also have the same issue. I tried like below for images.

            self.SPB.duration = 5
            self.SPB.isPaused  = true
            self.imagePreview.setShowActivityIndicator(true)
            self.imagePreview.setIndicatorStyle(.whiteLarge)
            self.imagePreview.sd_setImage(with: URL(string: storyDict.value(forKey: "storyUrl") as! String)) { (image, error, imageCacheType, imageUrl) in

                if image != nil {
                    print("image found")
            self.SPB.isPaused  = false

                }else
                {
                    print("image not found")
                }
                
            }

Before downloading image i am pausing the SegmentedProgressBar and after getting image again i am changing isPaused value to false. this is working only for first story.

if we have multiple stories below code executing after changing self.SPB.isPaused = true.
in that function self.isPaused = false. Because of that one again progress bar not Syncing with image .

private func animate(animationIndex: Int = 0) {
let nextSegment = segments[animationIndex]
currentAnimationIndex = animationIndex
self.isPaused = false // no idea why we have to do this here, but it fixes everything :D

    print("duration =* ",duration)
    
    UIView.animate(withDuration: duration, delay: 0.0, options: .curveLinear, animations: {
        nextSegment.topSegmentView.frame.size.width = nextSegment.bottomSegmentView.frame.width
    }) { (finished) in
        if !finished {
            return
        }
        self.next()
    }
}

Any useful reply will be appreciated. ^_^
Waiting for your good news! @@@👍
Thank you

Hi,
I Found one solution it working fine but I don't know exactly it is an efficient way or not.
in SegmentedProgressBar class I have placed if-else condition for checking ispaused value like below.

private func animate(animationIndex: Int = 0) {

    let nextSegment = segments[animationIndex]
    currentAnimationIndex = animationIndex
    
   **if self.isPaused {
        
    } else {
        self.isPaused = false // no idea why we have to do this here, but it fixes everything :D

    }**

    UIView.animate(withDuration: duration, delay: 0.0, options: .curveLinear, animations: {
        nextSegment.topSegmentView.frame.size.width = nextSegment.bottomSegmentView.frame.width
    }) { (finished) in
        if !finished {
            return
        }
        self.next()
    }
}

and for SegmentedProgressBar synchronization with video duration firstly i declared below three things globally.

var playerItem: AVPlayerItem!
private var playerItemContext = 0
let requiredAssetKeys = [
"playable",
"hasProtectedContent"
]

After that in play video or show image function i added some code like below.

func playVideoOrLoadImage(index: NSInteger) {

        let moviePath = storyDict["storyUrl"]as? String ?? ""
                    
        self.imagePreview.isHidden = true
        self.videoView.isHidden = false
        
        self.resetPlayer()
      
        let url = URL(string: moviePath)

        let asset = AVAsset(url: url!)

        playerItemContext = 0
        
        self.SPB.isPaused = true            
        playerItem = AVPlayerItem(asset: asset,
                                  automaticallyLoadedAssetKeys: requiredAssetKeys)
        
        playerItem.addObserver(self,
                               forKeyPath: #keyPath(AVPlayerItem.status),
                               options: [.old, .new],
                               context: &playerItemContext)
        
        player = AVPlayer(playerItem: playerItem)
        

        let videoLayer = AVPlayerLayer(player: self.player)
        videoLayer.frame = view.bounds
        videoLayer.videoGravity = .resizeAspectFill
        self.videoView.layer.addSublayer(videoLayer)
        
        let duration = asset.duration
        let durationTime = CMTimeGetSeconds(duration)
        self.SPB.duration = durationTime

        self.player.play()

}

When you associate a player item with AVPlayer, it immediately begins enqueuing the item’s media and preparing it for playback. The player item becomes ready for use when the status value changes to AVPlayerItem.Status.readyToPlay.

override func observeValue(forKeyPath keyPath: String?,
of object: Any?,
change: [NSKeyValueChangeKey : Any]?,
context: UnsafeMutableRawPointer?) {

    guard context == &playerItemContext else {
        super.observeValue(forKeyPath: keyPath,
                           of: object,
                           change: change,
                           context: context)
        return
    }
    
    if keyPath == #keyPath(AVPlayerItem.status) {
        let status: AVPlayerItemStatus
        if let statusNumber = change?[.newKey] as? NSNumber {
            status = AVPlayerItemStatus(rawValue: statusNumber.intValue)!
        } else {
            status = .unknown
        }
        
        switch status {
        case .readyToPlay:
            
            self.SPB.isPaused = false                
            break
        case .failed:
            
            self.SPB.isPaused = true
            break
        case .unknown:
            
            self.SPB.isPaused = true

            break
        }
    }
}

The above method is invoked whenever the status value changes, giving you the chance to take some action:
Now, everything works fine for me.

Hi, i have one issue regarding stories skipping. i need do exactly like whatsapp. For example if there are five stories, one user saw 3 stories out of five and close that screen. when the user reopen the same stories of that particular person i have to show image or play video from 4 th position of that stories. if Any body have idea kindly help me to fix this issue.

Hi, i have one issue regarding stories skipping. i need do exactly like whatsapp. For example if there are five stories, one user saw 3 stories out of five and close that screen. when the user reopen the same stories of that particular person i have to show image or play video from 4 th position of that stories. if Any body have idea kindly help me to fix this issue.

Hi, i have one issue regarding stories skipping. i need do exactly like whatsapp. For example if there are five stories, one user saw 3 stories out of five and close that screen. when the user reopen the same stories of that particular person i have to show image or play video from 4 th position of that stories. if Any body have idea kindly help me to fix this issue.

Did you found any solution on this @praveen4D2 ??

in playVideoOrLoadImage function stop SPB and resume after Load video or image:
self.SPB.isPaused = true

//add this code

override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.addObserver(self,
selector: #selector(playerItemDidReadyToPlay(notification:)),
name: .AVPlayerItemNewAccessLogEntry,
object: player?.currentItem)
}

@objc func playerItemDidReadyToPlay(notification: Notification) {
if let _ = notification.object as? AVPlayerItem {
// player is ready to play now!!
self.SPB.isPaused = false
}
}