Mini Tutorial: How to capture video of iPhone app in Cocos2D? with audio

Okay, so I figured out how to add audio to my video.

In my previous blog post (http://purplelilgirl.tumblr.com/post/10974345146/mini-tutorial-how-to-capture-video-of-iphone-app-in), I managed to take a video of my app and save it into a file. However I am just stringing together screenshots of my app taken at every 0.1 second, so it doesn’t capture the audio.

So I have a different function that is capturing my audio (AVAudioRecorder), and saving that into a file.

Now, to combine the files together. Since iOS 4.1, AVFoundation included this thing called AVMutableComposition, and with that you can make composites of stuff, like combine video and audio files together to make a new video file that has audio.

So code bits (I found bits of the code in StackOverflow):

-(void) processVideo: (NSURL*) videoUrl
{  
    AVURLAsset* videoAsset = [[AVURLAsset alloc]initWithURL: videoUrl options:nil];
   
    AVMutableComposition* mixComposition = [AVMutableComposition composition];
   
    AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
   
    NSError * error = nil;
   
    for (NSMutableDictionary * audioInfo in appDelegate.audioInfoArray)
    {
        NSString *pathString = [[NSHomeDirectory() stringByAppendingString:@”/Documents/”] stringByAppendingString: [audioInfo objectForKey: @”fileName”]];
       
        AVURLAsset * urlAsset = [AVURLAsset URLAssetWithURL:[NSURL fileURLWithPath:pathString] options:nil];
       
        AVAssetTrack * audioAssetTrack = [[urlAsset tracksWithMediaType:AVMediaTypeAudio] objectAtIndex:0];
        AVMutableCompositionTrack *compositionAudioTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeAudio
                                                                                       preferredTrackID: kCMPersistentTrackID_Invalid];
       
        NSLog(@”%lf”, [[audioInfo objectForKey: @”startTime”] doubleValue]);
       
        CMTime audioStartTime = CMTimeMake(([[audioInfo objectForKey: @”startTime”] doubleValue]*TIME_SCALE), TIME_SCALE);
       
        [compositionAudioTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero,urlAsset.duration) ofTrack:audioAssetTrack atTime:audioStartTime error:&error];     
    }
   
   
    AVMutableCompositionTrack *compositionVideoTrack = [mixComposition addMutableTrackWithMediaType:AVMediaTypeVideo
                                                                                   preferredTrackID:kCMPersistentTrackID_Invalid];
    [compositionVideoTrack insertTimeRange:CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
                                   ofTrack:[[videoAsset tracksWithMediaType:AVMediaTypeVideo] objectAtIndex:0]
                                    atTime:kCMTimeZero error:nil];
   
    AVAssetExportSession* _assetExport = [[AVAssetExportSession alloc] initWithAsset:mixComposition
                                                                          presetName:AVAssetExportPresetPassthrough];  
   
    NSString* videoName = @”export.mov”;
   
    NSString *exportPath = [[self pathToDocumentsDirectory] stringByAppendingPathComponent:videoName];
    NSURL    *exportUrl = [NSURL fileURLWithPath:exportPath];
   
    if ([[NSFileManager defaultManager] fileExistsAtPath:exportPath])
    {
        [[NSFileManager defaultManager] removeItemAtPath:exportPath error:nil];
    }
   
    _assetExport.outputFileType = @”com.apple.quicktime-movie”;
    NSLog(@”file type %@”,_assetExport.outputFileType);
    _assetExport.outputURL = exportUrl;
    _assetExport.shouldOptimizeForNetworkUse = YES;
   
    [_assetExport exportAsynchronouslyWithCompletionHandler:
     ^(void ) {
         switch (_assetExport.status)
         {
             case AVAssetExportSessionStatusCompleted:
                 //export complete
                 NSLog(@”Export Complete”);
                 //[self uploadToYouTube];
                
                 break;
             case AVAssetExportSessionStatusFailed:
                 NSLog(@”Export Failed”);
                 NSLog(@”ExportSessionError: %@”, [_assetExport.error localizedDescription]);
                 //export error (see exportSession.error) 
                 break;
             case AVAssetExportSessionStatusCancelled:
                 NSLog(@”Export Failed”);
                 NSLog(@”ExportSessionError: %@”, [_assetExport.error localizedDescription]);
                 //export cancelled 
                 break;
         }
     }];   
}

I have more than one audio file that I want to combine with my video, so I created a array file that contains information for each of the audio files (such as where the file is located and when to play that audio).

And that’s it 🙂 You have a video of your app 🙂 with audio 🙂

Advertisements

The App Store gamble continues…

Reblog of my AltDevBlogADay post.

My first blog post on #AltDevBlogADay is about the AppStore being a gamble. In this blog post, I will continue where my story left off.The App Store is a gamble, so what should you put your money on? The question continues, and will hopefully find some answers.

So, our company finished a game recently, it’s called “Absolute Instant” and it’s now available on the app store.

I am going to let tweets do the talking:

We are shocked because someone (that’s not us, or our friends) made a thread about our game on TouchArcade and people were talking about it. And then my boss is constantly Google-ing “Absolute Instant”, and all of us get so excited when we hear people writing reviews about it. There were good reviews and bad ones (mostly from the Japanese). There was one review in Japanese that described our game so bad, that one of the readers became intrigued and went to buy our game. So there really is no bad publicity, huh.

More tweets a conversation between me and my friend from the Philippines: (our conversation was mostly in Tagalog, so I will include translations)

31wpm: (My boss said our game has been pirated)

Google “Absolute Instant”, and you will see links to IPA download sites, they are mostly in Chinese, why they even gave our game a Chinese name, “巅峰时刻” (no idea how to read those words).

lendegracia: (that was quick)

And yes, sometimes, piracy can be a form of flattery. Because they liked our game enough to jailbreak it and share it to the world. Er..

31wpm: (they are so nice, they are helping us promote)

And hopefully, if our game is good enough, we will get our fair share. Hopefully.

Our company tweets too:

Most of the comments I received on my previous blog post about marketing. It’s not enough to just make an app, a game, that is good. You have to market it, and you have to market it well. Listed above are some of my bosses marketing efforts. Also our game designer also drops by all the Taiwanese and Chinese iPhone apps forums and starting threads and leaving comments. And one good thing about promoting it locally, the readers would say, “支持國產的遊戲” (which I think translates to, support games produced by your own country…? Okay, my Chinese is terrible), and they would proceed to buy it.

And the most exciting news we heard over the weekend, through luck, effort and divine intervention:

We are featured this week on the New and Noteworthy list for both Apps and Games. More stats:

All Games: #169
Top Arcade: #54
Top Action: #63
Game Center by Popularity: #83

The numbers are changing as we speak.

In our pep talk email from our boss, he mentions one very important thing, “Making the chart is one thing, but staying on the chart is another.” So still more marketing, more updates. Everything we can to keep our game rising on the list.

At the end of the day, there is not definitive answer that Arcade Shooters are the way to go, but for one thing, they were much more easy to market than our previous travel app.

Well, this is the story so far.

P.S. To all the nice people who have left comments and good advices on my previous post, thank you.

P.P.S. Game spiel:

Mobili Studio presents a new breed of shooting game designed base on iPhone’s unparalleled controls.

DRAG the circular region to move the fighting jets.
TAP anywhere to teleport out of enemies’ attacks.
SHAKE to drop a black hole bomb that sucks in all enemies’ bullets, even the smaller enemies!

Features:
•Unique teleporting gameplay (only possible on touchscreen!)
•3 difficulty levels
•2 characters with different attacks
•5 stages with bullet hell bosses
•Over 30 different enemy types
•Various magical attacks from special enemies and bosses
•Compatible with Game Center
•Built-in tutorial
•Awesome HD graphics
•Fast paced and adrenaline rushed music

Enter the war zone and conquer the Celestians using the breakthrough technology Terrestrians discovered – Absolute Instant (A.i.)! With this newfound power, the oppressed gained the ability to TELEPORT in the sky, and swore to end the centuries long battle…

P.P.P.S. Please support our game :) We also have a Lite version available. Please and thank you.

Links:

http://itunes.apple.com/us/app/absolute-instant/id426074497?mt=8#

http://itunes.apple.com/us/app/absolute-instant-lite/id439190029?mt=8

How to make fancy labels using Cocos2D?

UPDATE:

It’s been 2 years, and I am using Cocos2d again, and I discovered that the old Hiero binary seems to be buggy in OSX Lion, anyway, found  a newer build : http://www.cocos2d-iphone.org/forum/topic/220/page/2#post-145909.

—-

A very short tutorial.

I’m reading Cocos2D for iPhone Beginner’s Guide, and I’m reading Chapter 4 right now, called Pasting Labels, because I’m working on my game’s HUD. According to the book, there are three ways for displaying text in Cocos2D, first is CCLabel (which according to the author, is not very efficient, also it only supports the iOS fonts, which are Arial, Helvetica… which are not very much), and then there’s CCLabelAtlas (which is getting the characters from an image, you can do a lot of fancy effects using this, but the fonts has to be fixed width), and then there’s option number 3, which is CCBitmapFontAtlas.

The book introduced the Hiero Bitmap Font Tool for making CCBitmapFontAtlas (download link: http://slick.cokeandcode.com/demos/hiero.jnlp). So basically, I just followed the instructions in the book: download the software, run the software…

image

The book gave examples on how to use the Effects in Hiero, but I don’t find it sufficient, so I’m going to leave it plain, but I will add a bit of padding on the side (3, 3, 3, 3).

Go to File-> Save BMP font files…

It will save a .fnt and a .png. For some odd reason my .pngs are always inverted, so I open it in Photoshop…

image

I added the background, so you can see my text clearer. See, it’s inverted, so I just go to Image-> Image Rotation-> Flip Canvas Vertical.

The next step is double click on the Layer of the text or go to Layer-> Layer Style-> …

And add some fancy layer effects to your text. I only added Drop Shadow, but you can all sorts of fancy stuff, like Outer Glow, Bevel…

image

And then your text will look like this:

image

Save your file.

Drag the edited .png file and the .fnt file to your XCode project.

Some code for the CCBitmapFontAtlas:

CCBitmapFontAtlas * lblHighScoreTitle = [CCBitmapFontAtlas bitmapFontAtlasWithString:@”HIGH SCORE: ” fntFile:@”helveticaCY.fnt”];

And voila! You’re good to go!