I'm playing a video file from the documents directory, but I can't change the volume.
Actually I can play a file from the music video library and change the volume, but not for the precharged ( from iTunes with File Sharing ) videos!
What can I do?
That's the slider that is used like a crossfader between the videos for manage the volume:
AVMutableAudioMixInputParameters* audioInputParams2 = [AVMutableAudioMixInputParameters audioMixInputParameters];
CMTime currentTime = [videoItemDestra currentTime];
//se il video non c'è setta il tempo a zero, almeno non crasha
if(CMTIME_IS_INVALID(currentTime)){
currentTime = kCMTimeZero;
}
//se il pulsante muto è attivo non cambiare volume
if( mutedx ==1){
[audioInputParams2 setVolume:0 atTime:currentTime];
}else{
[audioInputParams2 setVolume:(_volumeSliderAvplayer2.value/100) atTime:currentTime];
}
[audioInputParams2 setTrackID:[videoDestra.tracks[0] trackID]];
NSMutableArray * allAudioParams2= [[NSMutableArray alloc]initWithObjects:audioInputParams2, nil];
AVMutableAudioMix * audioMix2 = [AVMutableAudioMix audioMix];
[audioMix2 setInputParameters:allAudioParams2];
AVMutableAudioMixInputParameters* audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParameters];
CMTime currentTime2 = [videoItemSinistra currentTime];
//se il video non c'è setta il tempo a zero, almeno non crasha
if(CMTIME_IS_INVALID(currentTime2)){
currentTime2 = kCMTimeZero;
}
//se il pulsante muto è attivo non cambiare volume
if( mutesx ==1){
[audioInputParams setVolume:0 atTime:currentTime2];
}else{
[audioInputParams setVolume:(1-(_volumeSliderAvplayer2.value/100)) atTime:currentTime2];
}
[audioInputParams setTrackID:[videoSinistra.tracks[0] trackID]];
NSMutableArray *allAudioParams= [[NSMutableArray alloc]initWithObjects:audioInputParams, nil];
AVMutableAudioMix* audioMix = [AVMutableAudioMix audioMix];
[audioMix setInputParameters:allAudioParams];
[videoItemSinistra setAudioMix:audioMix];
[videoItemDestra setAudioMix:audioMix2];
I found the solution.
When I load the track in the avplayeritem, that is divided in an "array" of audio, video, timecode ( if present ).
In case of video loaded from iTunes, the file had video, sound, timecode and I must load the sound part in the audiomix.
Before I discover that I load the avplayeritem[0] but it's wrong because in the file loaded from document library the sound part is in another position.
That's the solution:
//load the sound part in an array
audioTrackssx = [videoSinistra tracksWithMediaType:AVMediaTypeAudio];
//the sound part must be only one
[audioInputParams setTrackID:[audioTrackssx[0] trackID]];
Related
I want to send a external video from my iOS device.
This video is being received from a live streaming: RTSP server or HLS url (not from iPhone camera).
Currently I can stream my camera video from iPhone using VideoCore (internally using CameraSource and MicSource) but now, the video I want to stream comes from an URL. Similar to Periscope streaming video from GoPro Cam.
Problem 1: I don't know how to extract from a RTSP URL audio and video
Problem 2: I don't know how to create a CameraSource o MicSource from this extracted video and audio.
Do you know where to find an example or could you help me with this technical challenge?
I found a first approach for the first problem:
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:URL];
AVAsset *asset = [item asset];
[asset loadValuesAsynchronouslyForKeys:#[#"tracks"] completionHandler:^{
if ([asset statusOfValueForKey:#"tracks" error:nil] == AVKeyValueStatusLoaded) {
NSArray *videoTracks = [asset tracksWithMediaType:AVMediaTypeVideo];
NSArray *audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
//VIDEO
//videoOutput is a AVPlayerItemVideoOutput * property
[item addOutput:self.videoOutput];
//AUDIO
AVMutableAudioMixInputParameters *inputParams = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:[audioTracks objectAtIndex:0]];
MTAudioProcessingTapCallbacks callbacks;
callbacks.version = kMTAudioProcessingTapCallbacksVersion_0;
callbacks.clientInfo = (__bridge void *)self,
callbacks.init = tap_InitCallback;
callbacks.finalize = tap_FinalizeCallback;
callbacks.prepare = tap_PrepareCallback;
callbacks.unprepare = tap_UnprepareCallback;
callbacks.process = tap_ProcessCallback;
MTAudioProcessingTapRef tap;
OSStatus err = MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks,
kMTAudioProcessingTapCreationFlag_PostEffects, &tap);
inputParams.audioTapProcessor = tap;
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
audioMix.inputParameters = #[inputParams];
item.audioMix = audioMix;
}];
Then create a callback with CADisplayLink which will callback displayPixelBuffer: at every vsync.
self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:#selector(displayLinkCallback:)];
[[self displayLink] addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[[self displayLink] setPaused:YES];
and in this method get pixelBuffer and send to output
For Audio, do similar tasks in prepare callback using AURenderCallbackStruct.
So I am streaming a video file with audio using AVPlayer and have a UIWebView overlayed over the video that has controls for play/pause, seek, ect. I also have a slider for volume that I am trying to implement but so far I haven't had any luck. Here is my code the change the volume:
- (void)setPlayerVolume:(float)volume
{
NSArray *tracks = [self.player.currentItem.asset tracksWithMediaType:AVMediaTypeAudio];
NSMutableArray *audio = [NSMutableArray array];
for (AVAssetTrack *track in tracks) {
AVMutableAudioMixInputParameters *input = [AVMutableAudioMixInputParameters audioMixInputParameters];
[input setVolume:volume atTime:kCMTimeZero];
[input setTrackID:track.trackID];
[audio addObject:input];
}
AVMutableAudioMix *mix = [AVMutableAudioMix audioMix];
[mix setInputParameters:audio];
[self.player.currentItem setAudioMix:mix];
}
I have been reading up, and it seems like the only solution to use MPVolumeView. Are there any other solutions?
Thanks for any help, its greatly appreciated.
I wanted to change volume settings with a UISlider.
I used currentItem inside AVQueuePlayer.
ps0 is an AVQueuePlayer.
I have no error and same sound level when I use my UISlider:
- (IBAction)volumeSliderMoved:(UISlider *)sender
{
AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParameters];
AVPlayerItem *av = [ps0 currentItem];
CMTime currentTime = [av currentTime];
float volume = [sender value];
[audioInputParams setVolume:volume atTime:currentTime];
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
audioMix.inputParameters = [NSArray arrayWithObject:audioInputParams];
av.audioMix = audioMix;
[ps0 replaceCurrentItemWithPlayerItem: av];
}
EDITED :
I tried another solution from Apple to change volume settings.
As you can see in this solution, it create a new playerItem and a new player.
But my playerItem is a copy of the current one because I just want to change the sound (not the item). And it is automatically related to the old player.
When I try to use their solution. I have an error message saying:
An AVPlayerItem cannot be associated with more than one instance of AVPlayer
Any suggestion?
EDITED again
To change playback with AVQueuePlayer
I have an array with every mp3 name “textMissingTab”
I have an array with AVPlayerItem “soundItems”
Creation :
textMissingTab = [[NSArray alloc] initWithObjects:#"cat",#"mouse",#"dog",#"shark",#"dolphin", #"eagle", #"fish", #"wolf", #"rabbit", #"person", #"bird", nil];
for (NSString *text in textMissingTab)
{
NSURL *soundFileURL = [[NSURL alloc] initFileURLWithPath: [[NSBundle mainBundle] pathForResource:text ofType:#"mp3"]];
AVPlayerItem *item = [AVPlayerItem playerItemWithURL:soundFileURL];
[soundItems addObject:item];
}
Init :
NSURL *soundFileURL = [[NSURL alloc] initFileURLWithPath: [[NSBundle mainBundle] pathForResource:#"dog" ofType:#"mp3"]];
ps0 = [[AVQueuePlayer alloc] initWithURL:soundFileURL];
Change playItem : text is NSString
int index = [textMissingTab indexOfObject:text];
[ps0 setActionAtItemEnd:AVPlayerActionAtItemEndNone];
CMTime newTime = CMTimeMake(0, 1);
[ps0 seekToTime:newTime];
[ps0 setRate:1.0f];
[ps0 replaceCurrentItemWithPlayerItem:[soundItems objectAtIndex:(index)]];
[ps0 play];
I had several problems using AVQueuePlayer and changing playback parameters. If your goal is to use a slider for volume adjustment, I would replace the UISlider with a blank UIView in your storyboard and then instantiate an MPVolumeView within that view. This works reliably for me. Note that MPVolumeView does not show up on the simulator.
I think you are right tigloo. MPVolumeView is the best way to manage sound level.
It is explained in this tutorial :http://www.littlereddoor.co.uk/ios/controlling-system-output-volume-by-adding-an-mpvolumeview-object-to-an-ios-application/
"Everything works exactly as we would expect until the user hits the stumbling block that is created by the current ringer volume that is set on the device. The maximum value of the AVAudioPlayer property is 1.0, where 1.0 is equal to the current ringer volume setting of the device. Simply put, if the device ringer volume is set to 50% volume, then 100% of the AVAudioPlayer volume still only equates to the already set 50% ringer. The limitations of using this method speak for themselves."
I edited again my post to show how I manage some songs with AVQueuePlayer. This part of code is working.
AVAsset *asset;
NSArray *playerTracks;
NSMutableArray *playerParams;
AVMutableAudioMix *muteAudioMix;
for (int k=0; k<[[audio items] count]; k++)
{
//disable audio (this is the version when you have more than one video in the playlist: i write this version so it should be more useful)
asset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:[soundfile objectAtIndex:k+([soundfile count]-[[audio items] count])] ofType:#"mp3"]] options:nil];
playerTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
playerParams = [NSMutableArray array];
for (AVAssetTrack *track in playerTracks) {
AVMutableAudioMixInputParameters *audioInputParams = [AVMutableAudioMixInputParameters audioMixInputParameters];
[audioInputParams setVolume:1.0 atTime:kCMTimeZero];
[audioInputParams setTrackID:[track trackID]];
[playerParams addObject:audioInputParams];
}
muteAudioMix = [AVMutableAudioMix audioMix];
[muteAudioMix setInputParameters:playerParams];
[[[audio items] objectAtIndex:k] setAudioMix:muteAudioMix];
}
I am playing live streaming video in iPhone using AVPlayer. I want to switch off the volume of the player (programmatically). I tried this http://developer.apple.com/library/ios/#qa/qa1716/_index.html. But it is not working in my case.
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:[self myAssetURL] options:nil];
NSArray *audioTracks = [asset tracksWithMediaType:AVMediaTypeAudio];
// Mute all the audio tracks
NSMutableArray *allAudioParams = [NSMutableArray array];
for (AVAssetTrack *track in audioTracks) {
AVMutableAudioMixInputParameters *audioInputParams =[AVMutableAudioMixInputParameters audioMixInputParameters];
[audioInputParams setVolume:0.0 atTime:kCMTimeZero];
[audioInputParams setTrackID:[track trackID]];
[allAudioParams addObject:audioInputParams];
}
AVMutableAudioMix *audioZeroMix = [AVMutableAudioMix audioMix];
[audioZeroMix setInputParameters:allAudioParams];
// Create a player item
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithAsset:asset];
[playerItem setAudioMix:audioZeroMix]; // Mute the player item
// Create a new Player, and set the player to use the player item
// with the muted audio mix
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
// assign player object to an instance variable
self.mPlayer = player;
// play the muted audio
[mPlayer play];
Please suggest any solution for this.
Thanks
You can use MPVolumeView class, available [here]. It has a slider for volume control, that works for HTTP Live Streams as well.(http://developer.apple.com/library/ios/#documentation/mediaplayer/reference/MPVolumeView_Class/Reference/Reference.html)
I'm using AVPlayer for playing radio stream.
For initializing player i'm using next code:
self.asset = [AVAsset assetWithURL:self.url];
self.item = [AVPlayerItem playerItemWithAsset:self.asset];
self.player = [AVPlayer playerWithPlayerItem:self.item];
I've read this question Adjusting the volume of a playing AVPlayer
and i'm trying to set volume with slider value
- (void)setVolume:(float )volume
{
_volume = volume;
NSArray *audioTracks = self.asset.tracks;
NSMutableArray *allAudioParams = [NSMutableArray array];
for (AVAssetTrack *track in audioTracks) {
AVMutableAudioMixInputParameters *audioInputParams =
[AVMutableAudioMixInputParameters audioMixInputParameters];
[audioInputParams setVolume:volume atTime:kCMTimeZero];
[allAudioParams addObject:audioInputParams];
[audioInputParams setTrackID:[track trackID]];
}
AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix];
[audioMix setInputParameters:allAudioParams];
NSLog(#"%#", self.player.currentItem);
NSLog(#"%f", volume);
[self.player.currentItem setAudioMix:audioMix];
}
I'm also trying to set
[audioInputParams setVolume:volume atTime:self.player.currentTime];
but there are not any tracks in that array (self.asset.tracks),
and its have not any effect on volume. (also i can't get any metadata),
I can't use AVAudioPlayer for playing audio stream by url
An instance of the AVAudioPlayer class, called an audio player,
provides playback of audio data from a file or memory.
Apple recommends that you use this class for audio playback unless you
are playing audio captured from a network stream or require very low
I/O latency.
I'm thinking about using that code https://github.com/DigitalDJ/AudioStreamer/downloads
for playing radio stream, but i don't know how set volume with Audiotoolbox.
Please, help me! Thanks!
i have tried lots of solutions, but the best way to do that is to implement an instance ov MPVolumeVIew:
self.myViewVolume = [[MPVolumeView alloc] initWithFrame:CGRectMake(20, 330, 280, 50)];
[self.myViewVolume sizeToFit];
[self.view addSubview:self.myViewVolume];
You can add this to any UIView you want, just change the class to MPVolumeView
Do not forget to add MediaPlayer framework.
Here is what you have to do if you want to get metadata from your stream:
[playerItem addObserver:self forKeyPath:#"timedMetadata" options:NSKeyValueObservingOptionNew context:NULL];
With this you can simply add the information to any UILabel