AVFoundation Record Video for web playback -- has to download WHOLE file before playback starts - objective-c

I have an iPad app that records video and sends it to my SaaS application using AVFoundation. My web application then reads the file, and plays it using JWPlayer.
The problem I am having, is that JWPlayer (or any player I have tried) has to download the WHOLE video file before it will play. After doing some reading, I have discovered that the videos recorded from IOS don't have "fast start from internet" enabled. Or something along those lines.
I am using AVFoundation. Is there a different way to save the video so it will stream instantly from my web server? What am I missing.

The shouldOptimizeForNetworkUse property on AVWriter allows you to do this.
You could use it to rewrite the captured movie file prior to uploading to your server (or immediately post-capture, whatever suits I suppose).
Edit:
Okay, I'm not at a Mac at the moment, but something along these lines:
AVAsset *originalFile = [AVAsset assetWithURL:originalFileURL];
NSURL *outputFileURL = wherever you want to put it;
NSError *readerError;
NSError *writerError;
AVAssetReader *reader = [AVAssetReader assetReaderWithAsset:originalFile error:&readerError];
AVAssetWriter *writer = [AVAssetWriter assetWriterWithURL:outputFileURL fileType:AVFileTypeQuickTimeMovie error:&writerError];
writer.shouldOptimizeForNetworkUse = YES;
[writer startWriting];
...
and so on.

Related

Capture screen and audio with objective-c

I'm using an AVCaptureSession to create a screen recording (OSX), but i'd also like to add the computer audio to it (not the microphone, but anything that's playing through the speakers) i'm not really sure how to do that so the first thing i tried was adding an audio device like so:
AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
After adding this device the audio was recorded, but it sounded like it was captured through the microphone. Is it possible to actually capture the computer's output sound this way? like quicktime does.
Here's an open source framework that supposedly makes it as easy to capture speaker output as it is a screenshot.
https://github.com/pje/WavTap
The home page for WavTap does mention that it requires kernel extension signing privileges to run under MacOS 10.10 & newer, and that requires signing into your Apple Developer Account and submitting this form. More information can be found here.

UIVideoAtPathIsCompatibleWithSavedPhotosAlbum returns false when deploying on the iPhone

One of my app's features is to download a mp4 file and store it to the local phone album.
I have tried several approaches since and the result is always the same, it worked on the simulator but not on the actual iPhone. Xcode is version 5.0.1, iPhone 4.
Below is the code I applied on the last attempt before posted here using ASIHttpRequest library and the result is still the same, it worked on the simulator but not the phone itself.
download:
ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:url]; // url is the address to the mp4 file
NSString* filePath = [NSString stringWithFormat:#"%#%#", NSTemporaryDirectory(), filename]; //filename is the file I save to, e.g. xxx.mp4
[request setDownloadDestinationPath:filePath];
[request setDelegate:self];
[request setDidFinishSelector:#selector[ASIRequestDone:)];
[request setDidFailSelector:#select[ASIRequestFail:)];
when download is finished, save it to the photo album (in ASIRequestDone delegate)
if (UIVideoAtPathIsCompatibleWithSavedPhotosAlbum(filePath))
{
//comes to here when running in simulators
UISaveVideoAtPathToSavedPhotosAlbum(filePath, self, #selector(video:didFinishSavingWithError:cotextInfo:),nil);
}
else
{
//always comes to here when running on the actual iPhone.
}
I have checked the pathFile it's this
/private/var/mobile/Applications/xxxxxxxxxx/tmp/xxxxx.mp4
which is alright to me. What I am not getting is it works fine when running on Simulator and hence I am stuck not sure what to do next. (I have also checked the permission accessing the the photo albums and yes the app has it).
I also tried to removed the compatible checking and went straight into the method UISaveVideoAtPathToSavedPhotosAlbum, it didn't throw any error on delegate didFinishSavingWithError. however, the video didn't show up on the photo album either, I am guessing it's correct as the phone seems to say that video is not compatible to be shown on the album. Again, my issue is that it does work on the simulator and how do I fix this on the actual iphone, e.g. why it thinks the video is not compatible? is something to do with the mp4 itself or is it something to do during the download step? What could I do next to resolve the issue? (ps. I also have control over the mp4 files, is there a list of mp4 compatibility on the iphone that you know? I am thinking perhaps it's genuine that the file is not compatible on the phone (but on the simulator!?))
Found the answer to my question and I hope it could help out someone who suffers from the same issue. Turns out video resolution is the factor between the simulator and the actual phone when it comes to store video to the gallery; to be specific:
Compatibility checking UIVideoAtPathIsCompatibleWithSavedPhotosAlbum would FAIL on the actual phone but would PASS on the simulator given a sample clip capturrd as 1080p. I came cross this link a week after my post with luck.
"What video formats are compatible with the assets library?"
And I did the experiment similar to that by capturing 720p video clips instead and all files were able to be saved to the gallery. Weird thing is that the actual iphone can play the HLS stream at 1080p; howeve it won't store clips unless they are 720p, not to me anyway. And the misleading bit is that the simulator can actually do 1080p.

Open image from ALAsset representation in default Photos app

How can I open an image obtained from the Assets Library in the default 'Photos' app on iPhone? Ideally this should work without temporally storing a second instance of the image in my app's document folder.
I tried the following but there is no URL hook for "assets-library://":
NSURL *url = [NSURL URLWithString:#"assets-library://asset/asset.JPG?id=523360F1-385B-4E2D-8DF0-DA893AC631CE&ext=JPG"];
[[UIApplication sharedApplication] openURL:url];
Perhaps the better way is to use UIDocumentInteractionController, but it seems it would require saving the image to my documents folder first, which takes a few seconds on my device.
Thank you for any help!
Klaus
I don't believe iOS supports a URL scheme for opening specific photos in the photos app. If you want such a scheme to exist, the best you can do is file a radar.

Reading a .mov file with NSInputStream while writing with AVCaptureMovieFileOutput

Goal:
Use AVCaptureMovieFileOutput to record video to a .mov file. While video is recording, I want to upload it to S3. The uploading part should be feasible with Multi-Part upload. (Mac OS X +10.8 app)
Problem:
How do I read from a .mov file in chunks, while the file is being written to with AVCaptureMovieFileOutput and growing in size?
What I did so far:
// session = AVCaptureSession with audio and video inputs
fileOutput = [[AVCaptureSession alloc] init];
[session addOutput:fileOutput]
[session startRunning]
[fileOutput startRecordingToOutputFileURL: fileUrl recordingDelegate:self]
// In async dispatch queue
inputStream = [NSInputStream inputStreamWithFileAtPath:fileUrl]
// schedule in run loop, open and run
At this point I start receiving stream:handleEvent: messages on the delegate object with NSStreamEventHasBytesAvailable. But after a few seconds the messages stops coming in (after total bytes of 250.000-300.000 bytes (0.2MB)) This happens even though the .mov file grows in size to >10MB.
Questions:
Why does the NSInputStream delegate not continue to receive stream events?
Is the data available initially not reliable?
Is this overall a feasible approach? Or is there another way of achieving what I want?
Thanks!
I have a sample at http://www.gdcl.co.uk/2013/02/20/iOS-Video-Encoding.html that reads from a movie file while recording to the file from the camera (iOS 6). I'm using a separate AVAssetWriter, but it looks as though this should work fine for you.

iTunes Match + AVplayer + MPMediaQuery not working

I'm developing an app which makes usage of AVPlayer, MPMediaItem and MPMediaQuery. It works as long as Itunes match. We start with a MPMediaQuery, then we perform some filtering leaving some MPMediaItems, then we have been using AVPlayer because:
1.- we also play noises during the song play
2.- we need to suscribe to play/stops events from ipod.
All this features are currently working, except if the ipod library has itunes match enabled. Even when AVPlayer status is playing, no sound comes. Is obvious that it is not triggering the song download from iCloud.
All the information I have about itunes match by the moment is this post:
MPMediaItem and iTunes Match
which states you can trigger the download by using a MPMusicPlayerController play call. For the reasons given above, we cannot make use of this class to control our own player.
I have two ideas on how to solve this problem:
A. Find a way to check if a song is already downloaded and available in the library to play using AVPlayer. If the song is not available let the user know that we don't support songs not available.
B. Find a way to trigger the download of the song just before it becomes the next item to play.
I still cannot find how to implement any of these solutions and I haven't found any related documentation, so I submitted my app with a warning message to prevent users to use this app if they are using itunes match.
On iOS 6 and up you can use [[item valueForProperty:MPMediaItemPropertyIsCloudItem] boolValue] to check if an item is already downloaded.
A. Find a way to check if a song is already downloaded and available
in the library to play using AVPlayer. If the song is not available
let the user know that we don't support songs not available.
This isn't perfect but it works in most cases. Songs downloaded from iTunes Match will be DRM free. So you can check the assets DRM flags, if it is not exportable then it needs to be downloaded. It is possible to get a false positive with audio books/pod casts but you are mostly safe.
MPMediaItem* item
NSURL* url = [item valueForProperty:MPMediaItemPropertyAssetURL];
AVURLAsset* assetToLoad = [[AVURLAsset alloc] initWithURL:url options:nil];
bool protectedCon = assetToLoad.hasProtectedContent;
bool exportable = true;
if (gApp.mSysVersionInt >= 5) {
exportable = assetToLoad.exportable; //4.3+
}
B. Find a way to trigger the download of the song just before it
becomes the next item to play.
You can try doing this will a muted MPMusicPlayerController, but there is no way to track when the song is downloaded and sometimes it takes a very long time.