I am exporting a video with Some modifications.
After I get that exported video, I have the option to apply some more modifications Like Watermarking, Cropping, Video Rotation when I apply this transformation and export again the video quality is disturbed a strange green layer started appearing. Every time I export that video the green layer gets darker and darker. I am using the below code for exporting.
AVAssetExportSession *export = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
export.outputURL = [NSURL fileURLWithPath:exportPath];
if(videoComposition){
export.videoComposition = videoComposition;
}
if(audioComposition){
export.audioMix = audioComposition;
}
export.outputFileType = AVFileTypeQuickTimeMovie;
export.shouldOptimizeForNetworkUse = YES;
[export exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
if (export.status == AVAssetExportSessionStatusCompleted) {
completionHandler([export.outputURL relativePath],nil);
} else {
completionHandler(nil,export.error.localizedDescription);
}
});
}];
Related
I want to apply filter to AVVideoComposition by function:
init(asset: AVAsset, applyingCIFiltersWithHandler: (AVAsynchronousCIImageFilteringRequest) -> Void)
In which, the asset is AVComposition. When an AVPlayerItem plays this composition with the videoComposition, app crashes with error:
reason: '*** -[AVCoreImageFilterCustomVideoCompositor startVideoCompositionRequest:] Expecting video composition to contain only AVCoreImageFilterVideoCompositionInstruction'
I wonder how to fix the crash.
PS: I have two videoTracks in composition, each timeRange has its instruction
You can't use both AVVideoCompositionLayerInstruction and applyingCIFiltersWithHandler.
Intead, you need to apply directly the transform in the filter.
This can be done by applying it to the source image.
request.sourceImage.transformed(by: transform)
I guess you are trying to add AVVideoCompositionLayerInstruction to the AVVideoComposition.
Try the simple approach first and see if you need any changes:
AVURLAsset *asset = [AVURLAsset assetWithURL:videoURL];
CIFilter *filter = [CIFilter filterWithName:#"CIHueAdjust"]; // the filter you want to add: https://developer.apple.com/library/content/documentation/GraphicsImaging/Reference/CoreImageFilterReference/index.html#//apple_ref/doc/filter/ci/
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoCompositionWithAsset:asset applyingCIFiltersWithHandler:^(AVAsynchronousCIImageFilteringRequest * _Nonnull request) {
// set filter input image
[filter setDefaults];
[filter setValue:sourceImage forKey:kCIInputImageKey];
// hue
NSNumber *angle = [NSNumber numberWithFloat:0.8];
[filter setValue:angle forKey:kCIInputAngleKey];
CIImage *outputImage = filter.outputImage;
[request finishWithImage:outputImage context:nil];
}];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPreset1920x1080];
exportSession.outputFileType = AVFileTypeQuickTimeMovie;
exportSession.outputURL = outputURL;
exportSession.videoComposition = videoComposition;
// export the session async
[exportSession exportAsynchronouslyWithCompletionHandler:^{
switch (exportSession.status) {
case AVAssetExportSessionStatusCompleted:
NSLog(#"Yeah!");
break;
default:
NSLog(#"Nooo!");
break;
}
}];
AVMutableVideoComposition:videoCompositionWithAsset:applyingCIFiltersWithHandler only support iOS 9+ and if you only need export video with CIFilter, that's ok.
Configure more videoComposition instructions will cash, for example add kind of roateLayerInstruction to AVAssetTrack.
I have same issue in this situation and custom AVVideoCompositing maybe the better solution. some good demos about how to customize videoCompositor demo1 demo2.
I am working on this problem this week.
In my app, few audio files which are downloaded from server are not supported. mpeg,x-wav audio formats are not supported in my Objective-C code. How can I convert them into one of the supported types of iOS?
You could import them into garage band and then export as an IOS compatible format such as .m4a or .mp3
Below code maybe useful to you.And change the outputFileType what you want
AVAsset * asset = [AVAsset assetWithURL:inputURL];
AVAssetExportSession * exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
exportSession.outputFileType = AVFileTypeMPEG4;
exportSession.outputURL = outputURL;
exportSession.metadata = asset.metadata;
[exportSession exportAsynchronouslyWithCompletionHandler:^{
if (exportSession.status == AVAssetExportSessionStatusCompleted)
{
NSLog(#"AV export succeeded.");
}
else if (exportSession.status == AVAssetExportSessionStatusCancelled)
{
NSLog(#"AV export cancelled.");
}
else
{
NSLog(#"AV export failed with error: %# (%ld)", exportSession.error.localizedDescription, (long)exportSession.error.code);
}
}];
For Ref:-
https://stackoverflow.com/a/41053633
NOTE:- Not tested
After I export an AVMutableComposition I use PHPhotoLibrary to save the video to the camera roll. In the creationRequestForAssetFromVideoAtFileURL: completion handler, I then open the saved video in Instagram, like so:
__block PHObjectPlaceholder *videoAssetPlaceholder;
[[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
PHAssetChangeRequest *req = [PHAssetChangeRequest creationRequestForAssetFromVideoAtFileURL:localVideoURL];
videoAssetPlaceholder = req.placeholderForCreatedAsset;
} completionHandler:^(BOOL success, NSError *error) {
if (success) {
completion(YES);
NSString *localID = videoAssetPlaceholder.localIdentifier;
NSRange rangeOfSlash = [localID rangeOfString:#"/"];
if (rangeOfSlash.location != NSNotFound) {
NSString *assetID = [localID substringToIndex:rangeOfSlash.location];
NSURL *instagramURL = [NSURL URLWithString:[NSString stringWithFormat:#"instagram://library?AssetPath=%#", assetID]];
if ([[UIApplication sharedApplication] canOpenURL:instagramURL]) {
[[UIApplication sharedApplication] openURL:instagramURL];
}
}
}
}];
About 50% of the times Instagram opens and the video plays like expected. The other 50% of the times, however, both the video and the preview is white, and all I get is the sound. This usually gets fixed by selecting another video and then going back to my video. The video plays perfectly in the camera roll, it's only Instagram that causes problems. Is this an issue that Instagram has or could I be exporting my videos the wrong way?
These are my AVAssetExportSession settings:
AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset:mixComposition
presetName:AVAssetExportPresetHighestQuality];
exporter.outputURL = url;
exporter.outputFileType = AVFileTypeMPEG4;
exporter.shouldOptimizeForNetworkUse = YES;
exporter.videoComposition = mainCompositionInst;
[exporter exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
handler(exporter.outputURL);
});
}];
Just heard from Apple DTS. They also agree this points to an Apple iOS bug and asked me to log it.
I cut out usage of AVAssetExportSession like mentioned above and it solved my problem as a work around. So the issue seems to be around that method which is probably contained in the Instagram method you are using.
So until Apple fixes this or Instagram builds a work around, there does not seem to be a solution for this problem... Bummer
I have am iOS DVR application where i record and save video in .mp4 format in the document directory.
I am trying to move that video to camera roll but i am not able to move it.
I think it might be because of video format. Below is format of the video
H264 - MPEG-4 AVC
Resolution: 352 x 258
Frame rate: 15
I tried UISaveVideoAtPathToSavedPhotosAlbum but no luck.
I also tried to convert the video to another .mp4 using asset library using following code but status is always Failed.
[self convertVideoToLowQuailtyWithInputURL:localUrl outputURL:outputURL handler:^(AVAssetExportSession *exportSession)
{
if (exportSession.status == AVAssetExportSessionStatusCompleted) {
// Video conversation completed
}
}];
- (void)convertVideoToLowQuailtyWithInputURL:(NSURL*)inputURL outputURL:(NSURL*)outputURL handler:(void (^)(AVAssetExportSession*))handler {
[[NSFileManager defaultManager] removeItemAtURL:outputURL error:nil];
AVURLAsset *asset = [AVURLAsset URLAssetWithURL:inputURL options:nil];
AVAssetExportSession *exportSession = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetPassthrough];
exportSession.outputURL = outputURL;
exportSession.outputFileType = AVFileTypeMPEG4;
[exportSession exportAsynchronouslyWithCompletionHandler:^(void) {
handler(exportSession);
}];
}
How can I save recorded video file to camera roll ?
I have created a custom AVVideoComposition class and used it like this:
AVAsset *asset = ...
AVMutableVideoComposition *videoComposition = [AVMutableVideoComposition videoCompositionWithPropertiesOfAsset:asset];
videoComposition.customVideoCompositorClass = [MyCustomCompositor class];
MyCustomInstruction *instruction = // custom instruction holding CIFilter that is applied to every video frame
videoComposition.instructions = #[instruction];
After export session used like this:
AVAssetExportSession *session = [[AVAssetExportSession alloc] initWithAsset:asset presetName:AVAssetExportPresetHighestQuality];
session.outputURL = ...
session.outputFileType = AVFileTypeQuickTimeMovie;
session.videoComposition = videoComposition;
[session exportAsynchronouslyWithCompletionHandler:^{
...
}];
According to the documentation if I'm using AVVideoComposition, a track's preferredTransform won't work. Also with custom AVVideoCompostion instruction I can't set AVMutableVideoCompositionLayerInstruction with setTransform:atTime:.
How to get video with correct orientation?