I've saved a video to a file using:
NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
documentsDirectory = [documentsDirectory stringByAppendingPathComponent:#"test9.avi"];
NSLog(#"Open to: %#", documentsDirectory);
std::string fileName([documentsDirectory cString], [documentsDirectory cStringLength]);
videoWriter = new cv::VideoWriter(fileName, CV_FOURCC('H', 'F', 'Y', 'U'), 25, cvSize(288,352),1);
But I can't open this with VideoCapture:
NSLog(#"Load the video");
videoCapture = new cv::VideoCapture();
NSLog(#"Video loaded");
if (videoCapture->open(fileName))
{
NSLog(#"Opened");
}
else {
NSLog(#"Failed to open");
}
There is no error from the VideoCapture itself just my log "Failed to open" ...
Can I somehow get more detailed error log?
cv::VideoCapture capture;
NSString* pathToInputFile = [NSString documentPathByAppendingPath:#"Video/sample_iTunes.mov"];
if(capture.open(std::string([pathToFile UTF8String]))){
NSLog(#"Opened");
}else{
NSLog(#"Failed to open");
}
works fine for me
I met this problem using Swift 3.
Thanks to answers by Kirill and CodeBender, I solved this.
let resourceURL = Bundle.main.url(forResource: "test", withExtension: "MOV")
let openCVVideoCapture = OpenCVVideoCaptureWrapper.init(file: resourceURL?.path)
and following is my OpenCVVideoCaptureWrapper.mm
#implementation OpenCVVideoCaptureWrapper {
cv::VideoCapture video;
}
- (instancetype)initWithFile:(NSString*) filePath {
std::string cvFilePath = [filePath UTF8String];
video = cv::VideoCapture(cvFilePath);
if (!video.isOpened()) NSLog(#"Could not open file");
return self;
}
#end
This snippet worked for me in Xcode 10, Swift 4. Thanks to #Nathan Tuggy.
- (void)openVideoFile:(NSURL *)fileName {
NSString *filename = fileName.path;
std::string filePath = [filename UTF8String];
cv::VideoCapture capture(filePath);
if (!capture.isOpened()) {
printf("#Error Opening video file");
// failed, print error message
}
else {
printf("File Opened");
}
}
While Kirill's answer would have worked when it was posted, that is no longer the case now.
The following works in Xcode 8.2.1, replacing the documentPathByAppendingPath function that is no longer available.
cv::VideoCapture cap;
NSString *path = [[NSBundle mainBundle] pathForResource:#"MyVideo" ofType:#"MOV"];
if ( cap.open ( std::string( path.UTF8String ) ) ) {
NSLog(#"Opened");
} else {
NSLog(#"Failed to open");
}
Related
I saved the Image file in the Document Library in iOS device using Objective-C and it works in UI image.
In this case I want to upload the file somewhere (Like Dropbox) it uploads successfully but I can't open the file and the computer error says that "the image file (Image.jpg) can no be opened. It may be damaged".
Screenshot of the error
The problem is not in the uploading process because when I go to the document library folder I can not open that file neither.
The code that I used to save photos:
NSString *filePath = [self filesystemPathForURL:localURL];
CDVPluginResult* result = nil;
CDVFileError errCode = INVALID_MODIFICATION_ERR;
int bytesWritten = 0;
if (filePath) {
NSOutputStream* fileStream = [NSOutputStream outputStreamToFileAtPath:filePath append:shouldAppend];
if (fileStream) {
NSUInteger len = [encData length];
if (len == 0) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDouble:(double)len];
} else {
[fileStream open];
bytesWritten = (int)[fileStream write:[encData bytes] maxLength:len];
[fileStream close];
if (bytesWritten > 0) {
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:bytesWritten];
// } else {
// can probably get more detailed error info via [fileStream streamError]
// errCode already set to INVALID_MODIFICATION_ERR;
// bytesWritten = 0; // may be set to -1 on error
}
}
} // else fileStream not created return INVALID_MODIFICATION_ERR
} else {
// invalid filePath
errCode = NOT_FOUND_ERR;
}
if (!result) {
// was an error
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errCode];
}
return result;
I also try this code:
NSString *filePath = [self filesystemPathForURL:localURL];
[encData writeToFile:filePath atomically:YES];
encData is the NSData of the imagefile.
Change this
UIImage *image = [UIImage imageWithData:encData];
NSData *pngData = UIImagePNGRepresentation(image);
to
UIImage *image = [UIImage imageWithData:encData];
NSData *pngData = UIImageJPEGRepresentation(image);
Because your extension is .jpg but you are trying to write the png representation of the image that you have.
For some reason I am always receiving this error:
Error Domain=NSURLErrorDomain Code=-3000 "Cannot create file"
UserInfo={NSLocalizedDescription=Cannot create file,
NSUnderlyingError=0x1321dd730 {Error Domain=NSOSStatusErrorDomain
Code=-12115 "(null)"}}
when attempting to export an AVSession to m4a. This works fine on my co-workers device, however it fails every time on my iPad Air 2 (iOS 9.1), as well as our QA iPad Mini 3.
- (void)processSourceVideoFile:(NSURL *)mediaURL completion:(void (^)(BOOL success))completion {
[self showProgressOverlay];
NSString *outputFileType = AVFileTypeMPEG4;
__block NSString *videoID = nil;
if (self.videoAttachment == nil) {
[MagicalRecord saveUsingEditContextWithBlockAndWait:^(NSManagedObjectContext *localContext) {
self.videoAttachment = [SPXAttachment MR_createEntityInContext:localContext];
self.videoAttachment.uuid = [NSString uuid];
self.videoAttachment.clientCreatedAt = [NSDate date];
videoID = self.videoAttachment.uuid;
}];
} else {
videoID = self.videoAttachment.uuid;
}
self.videoAttachment = [SPXAttachment MR_findFirstByAttribute:#"uuid" withValue:videoID];
NSString *targetPath = self.videoAttachment.filePath;
DDLogVerbose(#"Exporting Video to %#", targetPath);
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath]) {
[[NSFileManager defaultManager] removeItemAtPath:targetPath error:nil];
}
AVAsset *video = [AVAsset assetWithURL:mediaURL];
self.exportSession = [AVAssetExportSession exportSessionWithAsset:video presetName:AVAssetExportPreset640x480];
self.exportSession.outputFileType = outputFileType;
self.exportSession.outputURL = [NSURL fileURLWithPath:targetPath];
[self.exportSession exportAsynchronouslyWithCompletionHandler:^{
dispatch_async(dispatch_get_main_queue(), ^{
[self hideProgressOverlay];
});
switch (self.exportSession.status) {
case AVAssetExportSessionStatusFailed:
DDLogError(#"Video Export Failed: %#", self.exportSession.error);
completion(NO);
break;
case AVAssetExportSessionStatusCancelled:
DDLogVerbose(#"Video Export Cancelled");
break;
case AVAssetExportSessionStatusCompleted: {
DDLogVerbose(#"Video Export Complete for %#", targetPath);
BOOL dir;
if ([[NSFileManager defaultManager] fileExistsAtPath:targetPath isDirectory:&dir]) {
DDLogVerbose(#"FILE IS THERE MOFO!!");
}
completion(YES);
}
break;
default:
break;
}
}];
}
Source URL: file:///private/var/mobile/Containers/Data/Application/BD85BA54-5B3D-4533-A142-C2A30F373814/tmp/capture-T0x12fe1e8e0.tmp.CbksL4/capturedvideo.MOV
Output URL: file:///var/mobile/Containers/Data/Application/BD85BA54-5B3D-4533-A142-C2A30F373814/Library/Files/59124681-ba1a-4453-8078-9ca6ac3088bf/attachments/454dd782-6b14-44cd-9f4e-84664908388b
I tried adding a file extension (.mp4) to the output URL and that did not help. I have searched around nothing quite matches this scenario.
Any help appreciated!
Make sure that your Output URL's path has the .mp4 file extension at the end.
You probably have a date in the file name with forward slashes.
Forward slashes are fine for a dir name but not a file name in a AVAssetExportSession.
Introduction
in my project, i've to delete folder and it's content(s) so i tried with this accepted answer ClickHere
it works and i thought that the task is over but after deleting a whole folder(Directory)i see that the memory is still allocated but file doesn't exist.here is my code to delete directory(folder).
-(BOOL)removeItem:(NSString*)name{
//name: is directory(folder)'s name
NSString*path = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
path = [path stringByAppendingPathComponent:#"Normal"];
path = [path stringByAppendingPathComponent:name];
NSError* err;
NSArray* list = [[NSFileManager defaultManager]contentsOfDirectoryAtPath:path error:&err];
if(err){
NSLog(#"\n##CONTENTS OF DIRECTORY ERROR:->\n%#",err.localizedDescription);
}
//if array's count is not zero(0) it means directory has files available.
if(list.count >= 1){
for(NSString* string in list){
[[NSFileManager defaultManager]removeItemAtPath:[path stringByAppendingPathComponent:string] error:&err];
if(err){
NSLog(#"\n##FOLDER IN FOLDER ERROR:->\n%#",err.localizedDescription);
}
}
[[NSFileManager defaultManager]removeItemAtPath:path error:&err];
return YES;
}else{
[[NSFileManager defaultManager]removeItemAtPath:path error:&err];
if (err) {
return NO;
}
return YES;
}
}
thanks in advance.
Alright, i got the issue.in my case the issue was a temp folder(directory). when i add video to my app, iOS created some temporary files in app's temp folder(directory). so, app's size i seen in setting->General->Usage->Manage Storage after removing the files(videos) from my app , was the size of temp folder.
so, when you import photos or videos from Gallery you have to manually clear the temp folder after fetching. i'm clearing the temp folder from UIImagePickerController's delegate as bellow.
-(void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary*)info{
[self dismissViewControllerAnimated:YES completion:^{
BOOL success = [videoData writeToFile:path atomically:YES];
NSLog(#"Successs:::: %#", success ? #"YES" : #"NO");
[RWTAppDelegate clearTmpDirectory];
}];
}
+ (void)clearTmpDirectory
{
NSArray* tmpDirectory = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:NSTemporaryDirectory() error:NULL];
for (NSString *file in tmpDirectory) {
[[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:#"%#%#", NSTemporaryDirectory(), file] error:NULL];
}
}
Update for swift 3+
class func clearTmpDirectory(){
let path = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
let manager = FileManager.default
let files = try? manager.contentsOfDirectory(atPath: path.path)
files?.forEach { (file) in
let temp = path.appendingPathComponent(file)
try? manager.removeItem(at: temp)
// --- you can use do{} catch{} for error handling ---//
}
}
sorry for my bad english.
I am creating MIDI sounds with MusicDeviceMIDIEvent and it's perfectly fine, I use some aupreset files I've created. One for each instrument.
My code is basically the example from apple: LoadPresetDemo. All I use is:
- (void)loadPreset:(id)sender instrumentName:(const char *)instrumentName {
NSString *presetURL1 = [NSString stringWithCString:instrumentName encoding:NSUTF8StringEncoding];
NSString *path = [[NSBundle mainBundle] pathForResource:presetURL1 ofType:#"aupreset"];
NSURL *presetURL = [[NSURL alloc] initFileURLWithPath: path];
if (presetURL) {
NSLog(#"Attempting to load preset '%#'\n", [presetURL description]);
}
else {
NSLog(#"COULD NOT GET PRESET PATH!");
}
[self loadSynthFromPresetURL: presetURL];
}
To load my aupreset file, then:
- (void) noteOn:(id)sender midiNumber:(int)midiNumber {
UInt32 noteNum = midiNumber;
UInt32 onVelocity = 127;
UInt32 noteCommand = kMIDIMessage_NoteOn << 4 | 0;
OSStatus result = noErr;
require_noerr (result = MusicDeviceMIDIEvent (self.samplerUnit, noteCommand, noteNum, onVelocity, 0), logTheError);
logTheError:
if (result != noErr) NSLog (#"Unable to start playing the low note. Error code: %d '%.4s'\n", (int) result, (const char *)&result);
}
to play the note of the previously loaded aupreset, and:
- (void) noteOff:(id)sender midiNumber:(int)midiNumber
when I want it to stop.
Now I would like to play one note of each instrument simultaneously. What is the easiest way of doing this?
I have been ploughing along with my learning of objective c and have got my app doing more or less everything I want it to do. I have the correct audio playing when certain buttons are pressed.
I have run in to some difficulty when localizing my audio file.
I have localized other elements of my app with no issue, for example I have used different images and button backgrounds and text by localizing in the same way but when I localize audio i run in to some issues and I can not find a solutions online as I normally do.
So as I said the issue only occurs when the file is localized, it effects the original language (where it was working before localizing the file) and the other languages (in this case French)
So the code I am using on my button is:
- (IBAction)domesticButtonClicked:(id)sender
{
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
resourcePath = [resourcePath stringByAppendingString:#"/localize-test.wav"];
// NSLog(#"Path to play: %#", resourcePath);
NSError* err;
//Initialize our player pointing to the path to our resource
domesticSound = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:resourcePath] error:&err];
if( err ){
//bail!
NSLog(#"Failed with reason: %#", [err localizedDescription]);
}
else{
//set our delegate and begin playback
domesticSound.delegate = self;
[domesticSound play];
domesticSound.numberOfLoops = 0;
domesticSound.currentTime = 0;
domesticSound.volume = 1.0;
}
}
}
So when this runs, instead of it playing the sound as it should I see the following in my output:
Failed with reason: The operation couldn’t be completed. (OSStatus error 2003334207.)
Can anyone shed any light on this for me?
Thanks in advance.
EDIT:
Thanks Marcus Adams, what you suggested does work but I can not use it on some buttons as i can not declare it every time.
So the reason the audio file is declared that way is so the audio file can be altered depending on the number of times the button has been clicked. Maybe this will help in getting my issue resolved.
- (IBAction)domestic03ButtonClicked:(id)sender
{
static int imageNumber = 0;
NSString* resourcePath = [[NSBundle mainBundle] resourcePath];
if (imageNumber == 0) {
domestic03ImageContainer.image = domestic300;
resourcePath = [resourcePath stringByAppendingString:#"/smb_coin1.wav"];
imageNumber++;
}
else if (imageNumber == 1) {
domestic03ImageContainer.image = domestic301;
resourcePath = [resourcePath stringByAppendingString:#"/smb_coin2.wav"];
imageNumber++;
}
else if (imageNumber == 2) {
domestic03ImageContainer.image = domestic302;
resourcePath = [resourcePath stringByAppendingString:#"/smb_coin3.wav"];
imageNumber++;
}
else if (imageNumber == 3) {
domestic03ImageContainer.image = domestic303;
resourcePath = [resourcePath stringByAppendingString:#"/smb_coin4.wav"];
imageNumber++;
}
else if (imageNumber == 4) {
domestic03ImageContainer.image = domestic304;
resourcePath = [resourcePath stringByAppendingString:#"/smb_coin5.wav"];
imageNumber = 0;
}
// NSLog(#"Path to play: %#", resourcePath);
NSError* err;
//Initialize our player pointing to the path to our resource
domesticSound = [[AVAudioPlayer alloc] initWithContentsOfURL:
[NSURL fileURLWithPath:resourcePath] error:&err];
if( err ){
//bail!
NSLog(#"Failed with reason: %#", [err localizedDescription]);
}
else{
//set our delegate and begin playback
domesticSound.delegate = self;
[domesticSound play];
domesticSound.numberOfLoops = 0;
domesticSound.currentTime = 0;
domesticSound.volume = 1.0;
}
domestic03ImageContainer.Alpha = 1;
}
You should be able to use just this for your path, assuming you've put the resource directly in the proper localized folder:
NSString* resourcePath = [[NSBundle mainBundle] pathForResource:#"localize-test"
ofType:#"wav"];
You should only check err if domesticSound == nil. This is generally true for APIs that take an NSError** in/out argument. (err is not guaranteed to be written to upon success.)
You should also initialize err to nil!