I've googled this question but did not find any solution.
So, my problem is,
I'm applying video filter using GPUImage
to a video file. At same time, sound of that video is not playing. I know that sound playing is not supported in GPUImage
while applying filters.
So, how can I achieve that?
You can achieve sound playing by adding support for AVPlayer
like this.
In GPUImageMovie.h
,
@property(readwrite, nonatomic) BOOL playSound;
In GPUImageMovie.m
, update @interface GPUImageMovie ()
like this.
@interface GPUImageMovie() <AVPlayerItemOutputPullDelegate>
{
// Add this
BOOL hasAudioTrack;
.........
........
// Add all below three lines
AVPlayer *theAudioPlayer;
CFAbsoluteTime startActualFrameTime;
CGFloat currentVideoTime;
}
After that, in -(void)startProcessing
method, add following lines.
- (void)startProcessing
{
// Add this
currentVideoTime = 0.0f;
.....
.....
// Add this
if (self.playSound)
{
[self setupSound];
}
GPUImageMovie __block *blockSelf = self;
[inputAsset loadValuesAsynchronouslyForKeys:[NSArray arrayWithObject:@"tracks"] completionHandler: ^{
runSynchronouslyOnVideoProcessingQueue(^{
.........
.........
// Add this
startActualFrameTime = CFAbsoluteTimeGetCurrent() - currentVideoTime;
.......
.......
});
}];
}
Again, In -(AVAssetReader*)createAssetReader
update it,
- (AVAssetReader*)createAssetReader
{
.......
.......
BOOL shouldRecordAudioTrack = (([audioTracks count] > 0) && (self.audioEncodingTarget != nil));
// Add this
hasAudioTrack = ([audioTracks count] > 0);
.........
}
In - (void)processAsset
,
- (void)processAsset
{
.......
.......
if ([reader startReading] == NO)
{
NSLog(@"Error reading from file at URL: %@", self.url);
return;
}
// Add this
if (self.playSound && hasAudioTrack)
{
[theAudioPlayer seekToTime:kCMTimeZero];
[theAudioPlayer play];
}
.........
.........
}
In -(void)endProcessing
,
- (void)endProcessing
{
.........
.........
if (self.playerItem && (displayLink != nil))
{
[displayLink invalidate]; // remove from all run loops
displayLink = nil;
}
// Add this
if (theAudioPlayer != nil)
{
[theAudioPlayer pause];
[theAudioPlayer seekToTime:kCMTimeZero];
}
.........
.........
}
Add new method -(void)setupSound
at last,
// Add this
- (void)setupSound
{
if (theAudioPlayer != nil)
{
[theAudioPlayer pause];
[theAudioPlayer seekToTime:kCMTimeZero];
theAudioPlayer = nil;
}
theAudioPlayer = [[AVPlayer alloc] initWithURL:self.url];
}
At last, when you create your GPUImageMovie
object, don't forget to set playSound
flag to YES.
Like this : movieFile.playSound = YES;
Hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With