iOS Movement of UISlider thumb to track the progress of the movie - ios

I'm implementing a video player in which I've taken UISlider to track the progress of the movie. This would mean that the thumb of the slider should be at the max value when the movie finishes.
I'm not able to achieve this. Movie finishes before thumb reaches at the end. Could anybody please help me understand what could be the issue?
This is the code that I've written:
//I'm setting the min, max values of the UISlider and calculating the current value
progressBar.minimumValue = 0.0;
progressBar.maximumValue = (float)movie.duration;
progressBar.value = ((float)movie.currentPlaybackTime/(float)movie.duration) * progressBar.frame.size.width;

Just use progressBar.value = (float)movie.currentPlaybackTime; instead of progressBar.value = ((float)movie.currentPlaybackTime/(float)movie.duration) * progressBar.frame.size.width;

Max value should be equal to the frame width:
progressBar.minimumValue = 0.0;
progressBar.maximumValue = progressBar.frame.size.width;
progressBar.value = ((float)movie.currentPlaybackTime/(float)movie.duration) * progressBar.frame.size.width;

Shouldn't it just be: progressBar.value = (float)movie.currentPlaybackTime ?
I mean, lets say movie duration is 60 sec, and the movie is at 15 sec (this is currentplaybacktime, I guess).
so:
progressbar min value is 0
progressbar max is 60
progressbar value should be between 0 and 60, and it is the value where the film is at right now: its 15.
Edit: You should also use: - setValue:animated:
Another idea: maybe you are not on the main thread. Make sure you are on the main thread when making ui changes.

Related

How to get the accurate time position of a live streaming in avplayer

I'm using AVPlayer to play a live streaming. This stream supports one hour catch-up which means user can seek to one hour ago and play. But I have one question how do I know the accurate position that the player is playing. I need to display current position on the player view. For example,if user is playing half an hour ago then display -30:00; if user is playing the latest content, the player will show 00:00 or live. Thanks
Swift solution :
override func getLiveDuration() -> Float {
var result : Float = 0.0;
if let items = player.currentItem?.seekableTimeRanges {
if(!items.isEmpty) {
let range = items[items.count - 1]
let timeRange = range.timeRangeValue
let startSeconds = CMTimeGetSeconds(timeRange.start)
let durationSeconds = CMTimeGetSeconds(timeRange.duration)
result = Float(startSeconds + durationSeconds)
}
}
return result;
}
To get a live position poison and seek to it you can by using seekableTimeRanges of AVPlayerItem:
CMTimeRange seekableRange = [player.currentItem.seekableTimeRanges.lastObject CMTimeRangeValue];
CGFloat seekableStart = CMTimeGetSeconds(seekableRange.start);
CGFloat seekableDuration = CMTimeGetSeconds(seekableRange.duration);
CGFloat livePosition = seekableStart + seekableDuration;
[player seekToTime:CMTimeMake(livePosition, 1)];
Also when you seek some time back, you can get current playing position by calling currentTime method
CGFloat current = CMTimeGetSeconds([self.player.currentItem currentTime]);
CGFloat diff = livePosition - current;
I know this question is old, but I had the same requirement and I believe the solutions aren't addressing properly the intent of the question.
What I did for this same requirement was to gather the current point in time, the starting time, and the length of the total duration of the stream.
I'll explain something before going further, the current point in time could surpass the (starting time + total duration) this is due to the way hls is structured as ts segments. Ts segments are small chucks of playable video, you could have on your seekable range 5 ts segments of 10 seconds each. This doesn't mean that 50 secs is the full length of the live stream, there is around a full segment more (so 60 seconds of playtime total) but it isn't categorized as seekable since you shouldn't seek to that segment. If you were to do this you'll notice in most instances rebuffering (cause the source may be still creating the next ts segment when you already reached the end of playback).
What I did was checking if the current stream time is further than the seekable rage, if so this would mean were are live on stream. If it isn't you could easily calculate how far behind you are from live if you subtract the current time, starting time, and total duration.
let timeRange:CMTimeRange = player.currentItem?.seekableTimeRanges.last
let start = timeRange.start.seconds
let totalDuration = timeRange.duration.seconds
let currentTime = player.currentTime().seconds
let secondsBehindLive = currentTime - totalDuration - start
The code above will give you a negative number with the number of seconds behind "live" or more specifically the start of the lastest ts segment. Or a positive number or zero when it's playing the latest ts segment.
Tbh I don't really know when does the seekableTimeRanges will have more than 1 value, it has always been just one for the streams I have tested with, but if you find in your streams more than 1 value you may have to figure if you want to add all the ranges duration, which time range to use as the start value, etc. At least for my use case, this was enough.

UISlider dividing into range

I want to do something like this. I have a UISlider its minimum value shuld be 0 and the maximum value should be 1000.And I want to divide this range into 10 parts. Like this.
0-----100----200----300----400
When user drag the slider from 0 it should directly stop at 100 position without stopping inbetween 0 and 100 when he drag from 100 it should directly jump into 200 should not stop inbetween 100 and 200 likewise.How can I do this? please help me.
Thanks
You have to do this:
slider.maximumValue = numberOfSteps;
slider.minimumValue = 0;
slider.continuous = NO;
For setting
NSUInteger index = (NSUInteger)(slider_value + 0.5);
[slider setValue:index animated:NO];
Well, just assign your slider range 0...10 and multiply changed value by 100
I had the same need just like you the day before. With default UISlider, you can only increment either +1 or -1. Hence, if you are looking to have a increment in other values, you have to do it programmatically.
In your case, try this:
- (IBAction)[yourUISlider]:(id)sender {
[[yourUISliderProperty] setValue:((int)(( [yourUISlider].value + 50) / 100) * 100) animated:NO];
NSLog(#"%d", [yourUISlider].value );
}
It worked for me, try it out :)
And for other increment values, check out the formula here:
((int)(( [yourSlider] + [yourIncrement/2] ) / [yourIncrement]) *[yourIncrement])
Then NSLog or output the value.

iOS - How to slow down UISlider at particular value

I am working on a customise UISlider where the MinimumValue is 0 and MaximumValue is 100. I want user to slow down the speed at the value of 50. For an example , if a user start sliding from 0 to 100 , it should work in a normal speed from 0-50 and then there should be a speed break at 50 and then the normal speed should be continued form 51-100.
Currently i have tried UISlider step size,
-(IBAction)valueChanged:(id)sender {
NSLog(#"Value : %f",roundf(_questionSlider.value));
float newStep = roundf((_questionSlider.value) / self.stepValue);
self.questionSlider.value = newStep * self.stepValue;
}

UISlider limitations in IPhone

In UISlider Control if I set "MinimumValue = 0" & "MaximimValue=2000" then I am not able to set the exact value. On release of slider thumb image it changes the value to + or - 5 to10. My slider width = 225px.
For example:- if I try to set the slider value to 100 then on release of slider thumb it shows me result like 105 or 95.
Code
IBOutlet UISlider * slider;
//"Slider" Object attached using XIB(.NIB)
slider.minimumValue = 0;
slider.maximumValue = 100;
//Attached Below Method Using XIB(.NIB) with "value Changed" event.
-(IBAction)slider_Change:(id)sender;
{
//Assigning value to UITextField
textFiled.text = [NSString stringWithFormat:#"%d",(((int) (slider.value)) * 20)];
}
Because you have set your slider range to be so large each pixel on the screen is equivalent to 8.888.
2000 / 255 = 8.8888888889
To get graduations of 1 you'll need to move the slider 1/8 of a pixel (this is impossible).
Alternatives are:
Make the slider longer
Reduce the slider range
Use a different control UIStepper
In addition to the answer by #rjstelling, it seems as if you are trying to convert the value of the slider to become an integer value. I believe that the default of the slider is a double value, this would cause the value to become rounded as it is increasing, since there will not be decimal values. Unless it is a requirement, see if you can use double.
textFiled.text = [NSString stringWithFormat:#"%f",(slider.value * 20.0)];
or if for some reason you'd want to restrict the level of decimal places you could go, you could do:
textField.text = [NSString stringWithFormat:#"%.1f", slider.value * 20.0];
This will give you the result of a decimal like 1.5 as your answer.
You could do anything with the decimal or even do something like %1.2f, %4.3f, or even %10.4f,
those will produce results like: 0.34, 0012.446, and something extreme like 000000345.1111
Hope this helps

Set the UiSlider interval to 0.5

I have a UISlider with minimumValue 0 and maximumValue. I want to make an interval of 0.5 and display it in a label (it's working).
How can I set the interval of my slider? I tried solution to round the value... but I failed.
Thank you
float RoundValue(UISlider * slider) {
return roundf(slider.value * 2.0) * 0.5;
}
when i do something like that i take an approach like the following:
#define kSTEPFRACTION .5
SliderMin = 0
sliderMax = 20
and get the value withs something like that
value = slider.value*kSTEPFRACTION;
this will give you values between 0 and 10 in steps of 0.5
sebastian

Resources