AvPlayer seekToTime issue - ios

I am working on video app and playing video on AVPlayer. But problem is when I seek the video to particular time with the help of UISlider. The player seekToTime method get time value in integer but I want that it gets in float. Please help
Here is my code
Float32 sliderValue = (float) avPlayerSlider.value;
[mPlayer seekToTime:CMTimeMake(sliderValue, 1) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];

You can set proper time scale.
CMTimeMake(12345, 10000); //This is 1.2345 seconds
Or use defined time scales
#define NSEC_PER_USEC 1000ull /* nanoseconds per microsecond */
#define USEC_PER_SEC 1000000ull /* microseconds per second */
#define NSEC_PER_SEC 1000000000ull /* nanoseconds per second */
#define NSEC_PER_MSEC 1000000ull /* nanoseconds per millisecond */
In my player app, I'm using such conversations:
CMTime thumbTime = CMTimeMakeWithSeconds(self.currentPlaybackTime, NSEC_PER_SEC);

I have also been plagued by this problem, fix it and the code below:
[_playerItem cancelPendingSeeks];
[_player seekToTime:CMTimeMakeWithSeconds(leftPosition, NSEC_PER_SEC) toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero];
leftPosition(CGFloat) is the time of the asset, the unit is a second.
I hope can help to you

Related

iOS how to slow down specific duration of video's playback speed

I want to make part of video slow down while rest of it are normal speed, just like the slow mode video taken by iOS camera. How to do that? I've search AVFoundation but found nothing.
Thanks!
If you are only talking about creating this effect during playback (and not exporting it), you should be able to do so by just changing the rate property of AVPlayer at specific times. Use addBoundaryTimeObserverForTimes:queue:usingBlock: to get notified when it's time to change the rate.
CMTime interval = CMTimeMake(10, 1);
NSArray *times = #[[NSValue valueWithCMTime:interval]];
_boundaryTimeObserver = [_avPlayer addBoundaryTimeObserverForTimes:times
queue:nil
usingBlock:^{
[_weakPlayer setRate:0.5];
}];
The rate property works as follows:
rate = 0.0; // Stopped
rate = 0.5; // Half speed
rate = 1.0; // Normal speed
For slow motion playback, the AVPlayer property canPlaySlowForward must be set to true.
Remember to remove the time observer when you're finished with it, and make sure to use an unretained reference to self or to the player within the block in order to avoid retain cycles.

AVPlayer seekTo not accurate

So I have an HLS stream that I have AVPlayer playing. I am trying to create a button to jump back 30 seconds like so:
- (void) rewindStream
{
NSLog(#"Seeking...");
NSLog(#"Current Time: %f", CMTimeGetSeconds(self.player.currentTime));
NSLog(#"New Time: %f", CMTimeGetSeconds(CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) - 30.0f, self.player.currentTime.timescale)));
[self.player pause];
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) - 30.0f, self.player.currentTime.timescale);
[self.player seekToTime:cmTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
NSLog(#"Complete. Current Time: %f", CMTimeGetSeconds(self.player.currentTime));
[self.player play];
}];
}
Which works sometimes, but not others. Here is the log:
Seeking...
Current Time: 47.253361
New Time: 37.254001
Complete. Current Time: 37.254944
Seeking...
Current Time: 59.409800
New Time: 49.410447
Complete. Current Time: 50.103244
Seeking...
Current Time: 68.780054
New Time: 58.780436
Complete. Current Time: 60.086244
Seeking...
Current Time: 80.493733
New Time: 70.494375
Complete. Current Time: 80.140578
Seeking...
Current Time: 92.674773
New Time: 82.675062
Complete. Current Time: 110.135244
I have the tolerance set, and I am making sure I give enough time for the segments to download/buffer so that seeking is possible, but I am not sure what the issue could be.
Any help would be greatly appreciated.
Thanks.
I always use a timescale of 60000 which gives enough accuracy for almost anything. Not sure if this is your issue but I've found that most of my CMTime problems came before I settled on this. Warren Moore has a great post describing this at http://warrenmoore.net/understanding-cmtime
It looks right, off the top of my head, maybe something like this?
CMTime currentTime = self.player.currentTime;
CMTime timeToSubtract = CMTimeMakeWithSeconds(30, 1);
CMTime resultTime = CMTimeSubtract(currentTime, timeToSubtract);
[self.player seekToTime:resultTime];

iOS - AVPlayer seekToTime restarts playback of currentItem

I'm making an app that uses AVPlayer. In one of my views I have a UISlider with which the user should be able to scrub forward and backward. I'm having some trouble getting seekToTime to work as I want. When I try to change time the playback starts from 0, and I'm not sure how to solve this. My current implementation looks like this:
[self.progressSlider addTarget:self action:#selector(sliderValueChanged) forControlEvents:UIControlEventValueChanged];
[self.progressSlider addTarget:self action:#selector(sliderReleased) forControlEvents:UIControlEventTouchUpInside];
- (void)sliderValueChanged {
[...]
[player pause];
}
- (void)sliderReleased {
float timeInSecond = self.progressSlider.value;
timeInSecond *= 1000;
// I have trie to hard code this value, but I get the same result.
CMTime cmTime = CMTimeMake(timeInSecond, NSEC_PER_SEC);
[player.currentItem seekToTime:cmTime toleranceBefore:kCMTimeZero toleranceAfter:kCMTimeZero completionHandler:^(BOOL finished) {
if (finished) {
[player play];
}
}];
}
Any ideas on what I'm doing wrong?
Can mention that I stream audio using AVPlayer's: playerItemWithURL if that makes any difference.
One problem is that NSEC_PER_SEC is 1,000,000,000, so CMTimeMake(timeInSecond, NSEC_PER_SEC) is going to be a really tiny number (unless timeInSecond is ridiculously huge) - in fact, it will be arbitrarily close to zero, which is exactly what you are experiencing.
Just to be clear: CMTimeMake defines a rational number. You are giving a numerator and a denominator. If your denominator is huge, the rational number will be tiny.

Image Animation with Sounds

I have an image animation with total duration of 2 seconds and in total 6 images. It's a blinking button. I want to play a sound every time that button blink, so in interval of 0.66 seconds by 3 times. I tried do this but the last sound play its a microsecond delay that i dont want..What i can do to play the sound right?
I'm doing this:
-(void)playAnswerAnimSound
{
if(audioActive)
{
if(answerAnimCounter <3)
{
//AudioServicesDisposeSystemSoundID(answerAnimSound);
AudioServicesPlaySystemSound(answerAnimSound);
[answerAnimTimer invalidate];
answerAnimTimer = [NSTimer scheduledTimerWithTimeInterval:0.6666 target:self selector:#selector(playAnswerAnimSound) userInfo:nil repeats:NO];
answerAnimCounter++;
}
else if(answerAnimCounter == 3)
{
answerAnimCounter =0;
[answerAnimTimer invalidate];
}
}
}
The sound duration is 1 second.
Regards
You cannot sync audio by just generating calls to audio services at time intervals, you need to actually render out a .wav or .m4a file with all the audio clips already spaced out in time. Then, playback the generated audio as 1 longer clip and sync the video to the audio. See the linked answer for more details about the implementation.

AVPlayer provide wrong currenttime and duration iOS when seek the video many times?

I use use AVPlayer to implement a custom player.
Some video playerItem provide the current time and wrong duration. After to seek time use slide to seek time many times. Call the API
When I seek to zero, some video can not be precisely seeked.
[self.player seekToTime:CMTimeMakeWithSeconds(time, NSEC_PER_SEC)
toleranceBefore:CMTimeMake(1, 1)
toleranceAfter:CMTimeMake(1, 1)
completionHandler:^(BOOL finished) {
if (finished) {
IVCLogV(#"seek finish!");
}
else
{
IVCLogV(#"seek interrupted");
}
if (completionHandle) {
completionHandle(finished);
}
}];
I change the codes according the mediaTime.timeScale. Now I discover the video stream have changed the video duration and current time after several play.
Make sure that the Timescale of the media being played matches with your timescale. I can see you have used NSEC_PER_SEC as timescale. You may have to scale your CMTime input to seelTo method.
CMTime timeAccordingToMediaTimescale = CMTimeConvertScale(time, mediaTime.timescale, CMTimeRoundingMethod);

Resources