Display only a fraction of video using AVPlayer - iphone

I have a requirement where I am displaying a media library video (AVAsset) using AVPlayer and updating the current frame in the video using a custom slider in the UI.
However, what I am looking for is how to tie the slider with the video without actually trimming the video.
I want to show a fraction of video attached to the slider i.e. say I have a video of duration 10 secs. I want the slider to be attached to 3-6 secs, which means if the slider is at start it should show the frame at 3.0 secs in the video and if the slider is at end it should show the frame at 6th sec in the video.
Simply put, to the user it should appear as the video is only of total duration 3 secs.
P.S. There is a lot in the above question, but I've tried my best to simplify my query.

1) Seek to start position:
int32_t preferredTimeScale = 600;
CMTime inTime = CMTimeMakeWithSeconds(self.startTime, preferredTimeScale);
[mainPlayer seekToTime:inTime];
2) Set a timer:
_EndOFRegionCheckTimer = [NSTimer scheduledTimerWithTimeInterval:0.10f
target:self
selector:#selector(_checkEndPassedFired)
userInfo:nil
repeats:YES];
3) In timer fire event check current position and stop playing if necessary:
- (void)_checkEndPassedFired {
AVPlayerItem *currentItem = mainPlayer.currentItem;
if ((double)currentItem.currentTime.value/currentItem.currentTime.timescale>self.stopTime)
{
[mainPlayer pause];
}
}

Related

Making a timer to very slightly delay several audio channels for iPhone app?

I have 5 audio channels being operated by five AVAudioPlayer objects, and I would like to add a very small delay to each of these channels, so that when I push a button, I get this:
Start sound 1 (which lasts 10 seconds)
Start sound 2 0.25 seconds after sound 1
Start sound 3 0.25 seconds after sound 2
Start sound 4 0.25 seconds after sound 3
Start sound 5 0.25 seconds after sound 3
I tired to do this just using sleep(0.25) between each calling of [AVAudioPlayerObeject play] like this:
[audioPlayer1 play];
sleep(delay);
[audioPlayer2 play];
sleep(delay);
[audioPlayer3 play];
sleep(delay);
[audioPlayer4 play];
sleep(delay);
[audioPlayer5 play];
...where delay is a float variable set to 0.25. However, this doesn't work, and I hear all 5 sounds at once. I tried experimenting with NSTimer, but I didn't really understand how to make a separate method for the delay, and then call the method with my code.
Can someone please help me revise my code to get the desired effect? Thanks!
Keep state with an integer that identifies which sound to start...
#property(assign, nonatomic) NSInteger startSound;
Schedule a timer...
self.startSound = 0;
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:0.25 target:self selector:#selector(timerFired:) userInfo:nil repeats:YES];
When the timer fires, start a new sound. Quit after you've started 5....
- (void)timerFired:(NSTimer *)timer {
if (self.startSound < 5) {
// assume you know how to play sound N, numbered 0..4
[self playSound:self.startSound++];
} else {
[timer invalidate];
}
}
You can make the timer interval and the max count of sounds variables in this class.

UISlider value assigining issue ios

I'm using a UISlider programmatically in a MPMoviePlayerController and set its value with the movie current playback time. This doesn't work properly in some cases, the value of the slider remains zero not changed with the movie's current playback time. Can anyone help me please?
My code is set to fire after each second. Both labels work properly but the UISlider value doesn't get updated and remains zero.
float playbackTime = player.currentPlaybackTime;
float duration = player.duration;
timeLabel.text = [NSString stringWithFormat:#"%.0f / ",playbackTime];
durationlbl.text=[NSString stringWithFormat: #"%.0f",`duration];`
progressSlider.value = playbackTime;
you should probably do this:
progressSlider.minimumValue = 0.0;
progressSlider.maximumValue = player.duration;
you should do this not all the times that you update the slider but only when you initialize the slider or when you start a new video
i resolved this issue by stop the video on close action of the player before play other video.
this issue occur because of previous video state in the player due to which on launching new video slider valur disturbed.

How to make progressive UISlider like UIProgressView in AVAudioPlayer as song is being playing?

Actually i made that while song is playing in AVAudioPlayer, Slider is progressed as song running. Also i made if i seek it to forward or backward, from that position current song is playing.
But the problem is after seeking the slider to particular position it not progressed and stop there but still song is running from that position.
The code below :
Blockquote
myTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:#selector(updateMyProgressOfCurrentPlayingSong:) userInfo:nil repeats:YES];
-(void)updateMyProgressOfCurrentPlayingSong:(NSTimer *)theTimer{
//For Current Song Playing Slider
float progr = [mediaPlayer currentTime]/[mediaPlayer duration];
self.audioCurrentPlayingSlider.value = progr;
}
//For Slider Value change
-(IBAction)audioCurrentSongPlayingSlider:(id)sender {
[myTimer invalidate];
myTimer = nil;
[self.audioCurrentPlayingSlider setMinimumValue:0.0];
[self.audioCurrentPlayingSlider setMaximumValue:[mediaPlayer duration]];
[mediaPlayer setCurrentTime:[self.audioCurrentPlayingSlider value]];
[myTimer methodForSelector:#selector(updateMyProgressOfCurrentPlayingSong:)];
}
Blockquote
See following link which may help you,
1)How to add UISlider to AVPlayer
2)UISlider to control AVAudioPlayer
3)Create a UISlider progress bar and timer (like iPod player) within app
4)http://www.mobisoftinfotech.com/blog/iphone/integrate-music-player-in-iphone/

How to perform operations when playing sound in iPhone?

I play a MP3 in my iPhone app using AVAudioPlayer; i need to perform some operations at certain times (say 30th seconds, 1 minute); is there a way to invoke callback functions based on mp3 playing time?
I believe the best solution is to start an NSTimer as you start the AVAudioPlayer playing. You could set the timer to fire every half second or so. Then each time your timer fires, look at the currentTime property on your audio player.
In order to do something at certain intervals, I'd suggest you kept an instance variable for the playback time from last time your timer callback was called. Then if you had passed the critical point between last callback and this, do your action.
So, in pseudocode, the timer callback:
Get the currentTime of your AVAudioPlayer
Check to see if currentTime is greater than criticalPoint
If yes, check to see if lastCurrentTime is less than criticalPoint
If yes to that too, do your action.
Set lastCurrentTime to currentTime
If you're able to use AVPlayer instead of AVAudioPlayer, you can set boundary or periodic time observers:
// File URL or URL of a media library item
AVPlayer *player = [[AVPlayer alloc] initWithURL:url];
CMTime time = CMTimeMakeWithSeconds(30.0, 600);
NSArray *times = [NSArray arrayWithObject:[NSValue valueWithCMTime:time]];
id playerObserver = [player addBoundaryTimeObserverForTimes:times queue:NULL usingBlock:^{
NSLog(#"Playback time is 30 seconds");
}];
[player play];
// remove the observer when you're done with the player:
[player removeTimeObserver:playerObserver];
AVPlayer documentation:
http://developer.apple.com/library/ios/#documentation/AVFoundation/Reference/AVPlayer_Class/Reference/Reference.html
I found this link describing a property property which seems to indicate you can get the current playback time.
If the sound is playing, currentTime is the offset of the current
playback position, measured in seconds from the start of the sound. If
the sound is not playing, currentTime is the offset of where playing
starts upon calling the play method, measured in seconds from the
start of the sound.
By setting this property you can seek to a specific point in a sound
file or implement audio fast-forward and rewind functions.
To check the time and perform your action you can simply query it:
if (avAudioPlayerObject.currentTime == 30.0) //You may need a more broad check. Double may not be able to exactly represent 30.0s
{
//Do Something
}
with multithreading your goal is simple, just do like this :
1 : in your main thread create a variable for storing time passed
2 : create new thread like "checkthread" that check each 30-20 sec(as you need)
3 : if the time passed is what you want do the callback
Yes Sure you can ...it's tricky i hope it works for you but it works for me ..
1- you play your mp3 file.
2- [self performSelector:#selector(Operation:) withObject:Object afterDelay:30];
then the function
-(void)Operation:(id)sender;
called; so you fired function after 30 second of mp3 file .. you can make many of function based on time you want..
3- there is other solution using timers
[NSTimer scheduledTimerWithTimeInterval:0 target:self selector:#selector(CheckTime:) userInfo:nil repeats:YES];
it will fire function called Check Time
-(void)CheckTime:(id)sender{
if (avAudioPlayerObject.currentTime == 30.0)
{
//Do Something
//Fire and function call such
[self performSelector:#selector(Operation:) withObject:Object]
}
}
then you can change time interval you want and repeats is for you to control repeat this action every 5 seconds or not..
Hope that helpful..
Thanks
i think ,you want to play different sound-files after 30sec then use this code :
1) all sound-files put in Array and then retrieve from document directory
2)then try this:
-(IBAction)play_sound
{
BackgroundPlayer=[[AVAudioPlayer alloc]initWithContentsOfURL:[NSURL fileURLWithPath:[[NSBundle mainBundle]pathForResource:[Arr_tone_selected objectAtIndex:j]ofType:#"mp3"]]error:NULL];
BackgroundPlayer.delegate=self;
[BackgroundPlayer play];
}
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
[BackgroundPlayer stop];
j++;
[self performSelector:#selector(play_sound) withObject:Object afterDelay:30];
}

How can you play a sound of a specified duration using AVAudioPlayer on iOS?

I want to play a specified duration within a sound file on IOS. I found a method in AVAudioPlayer that seeks to the begining of the playing (playAtTime:) but i cannot find a direct way to specify an end time before the end of the sound file.
Is there is a way to achieve this?
If you don't need much precision and you want to stick with AVAudioPlayer, this is one option:
- (void)playAtTime:(NSTimeInterval)time withDuration:(NSTimeInterval)duration {
NSTimeInterval shortStartDelay = 0.01;
NSTimeInterval now = player.deviceCurrentTime;
[self.audioPlayer playAtTime:now + shortStartDelay];
self.stopTimer = [NSTimer scheduledTimerWithTimeInterval:shortStartDelay + duration
target:self
selector:#selector(stopPlaying:)
userInfo:nil
repeats:NO];
}
- (void)stopPlaying:(NSTimer *)theTimer {
[self.audioPlayer pause];
}
Bear in mind that stopTimer will fire on the thread's run loop, so there will be some variability in how long the audio plays, depending on what else the app is doing at the time. If you need a higher level of precision, consider using AVPlayer instead of AVAudioPlayer. AVPlayer plays AVPlayerItem objects, which let you specify a forwardPlaybackEndTime.