recording quicktime with sound in sync

I am in the middle of making a sort of interactive photo/video booth, the end outcome is short video clips recorded to disk that have sound embedded in the video clips. Sound is played from script in ofw.

I briefly touched on this subject before, although my intentions were misunderstood.

So I’m back on this topic now and have been testing out zachs memory-movie-maker

  1. As you add more frames to the video, of course the memory increases and the framerate drops. The flattened movie starts off ok and then speeds up towards the end.

I’ve tried ofSetFrameRate with little effect.

Do you think creating a file and adding to that file, rather than a movie object in memory, would solve this problem, or are we always going to get slowdown when trying to create a movie?

  1. Rather than trying to write something using the quicktime api, might it be better to somehow save a quicktime of the screen & audio to disk using seperate programs, and try to script it to combine the two files together (in something like applescript)?

Any thoughts on quicktime movie creation much appreciated.

I’m currently looking through the quicktime sample-programs

hi chris,

this is a fix to the code I posted earlier –

openFrameworks.cc/files/movieSaver/movie_recorder_fix_01.zip

it cleans up some memory issues with the earlier example. It might take some hacking to get this to work on a mac though.

some answers -

  1. doing it to disk would be better then doing it in memory – I was doing that because I was curious, but the code will be simpler and likely no memory fluctuations.

also, about frame rate, you can pass in somewhere how long a frame is lasting, and that should help in some sense to even it out and make the movie smooth.

  1. could be – I don’t know about audio or how to do it, but I think it’ would be pretty simple. take a look at the part of the code were raw graphics data is passed in. it’d be the same sort of call for audio, and similar calls to setup the audio compressor format, etc.

I learned alot from this page:
http://www.enete.com/noel/nuggets-quicktime/

and the apple developers mailing list is pretty active, you can always ping them and explain what you are working on.

good luck!
zach

Thanks Zach, will let you know how I get on.

Slightly off topic (ish) but to get over the framerate drop issue, I am storing the pixels in a buffer, then when you stop recording, tell the memorymoviemaker to create a new movie, cycle through and add each frame from the buffer, then stop making the movie and save.

this way there is no drop in framerate, you just have to wait a little while whilst the movie is created at the end.

my basic knowledge of pointers & vectors is letting me down…

  
  
// .h  
vector <unsigned char *> framesBuffer;  
  
// .cpp   
framesBuffer.push_back( videoGrabber.getPixels() );  
  

every frame of the video is the same (the last frame stored in videoGrabber at time of save).

So I tried…

  
  
unsigned char * pixels = new unsigned char[w* h* 3];  
memcpy(pixels, vidGrabber.getPixels(), sizeof(pixels));  
framesBuffer.push_back( pixels );  
  

However that doesn’t work either (all black). Whats the best way to copy the current video pixels into my vector list, ideally without having to create a new and delete a temporary pixel unsigned chars.

Many thanks

ok, for some reason this works
**memcpy(pixels, vidGrabber.getPixels(), (w*h*3)); **

By the way, in movie_recorder_fix_01 save() no longer works (no error, no file output) - (windows xp, vs 2005). Any thoughts?

saveViaFileDialog() has never worked for me, always crashes upon calling. It is this line:

  
  
StandardPutFile(c2pstr("Enter movie file name:"), c2pstr("untitled.mov"), &sfr);  
  

hmm – I must have uploaded not the latest version

if you change this line in the movieMaker:

  
  
	sprintf(buffer, "%s//%s",  cwdir, fileName);  
  

to

  
  
	sprintf(buffer, "%s\\%s",  cwdir, fileName);  
  

this isn’t putting them in the data folder however – it would have to be fixed… right now it saves them directly in bin…

about saveByfileDialog, I know that there is a problem but I didn’t really work on that. will take a look, but save() should definitely work with above fix.

best!!
zach

I’ve made the change to save() but no luck.
I’ve debugged the function to see where it trips up. Its here:

  
  
if (EndMediaEdits(myMedia)  != noErr){  
  

Any ideas? Thanks

I don’t know - it works fine for me –

are you trying the example code with the fix or are you using your own usage?
I’d try the example first.

best
zach

Hi,

I’m trying the example is OS X but it isn’t compiling, says I’m missing the files “QTML.h”, “FixMath.h”, “QuickTimeComponents.h”, “TextUtils.h”, “Resources.h”, and “direct.h”.

I did not add the “QTDevWin” directory to the project since it has “Win” in the name, but I did add the Quicktime Framework (from the 10.4 SDK).

Chris, I believe you’re working on OS X, could you give me some pointers?

Thanks

Sorry I’m on Windows. Not sure what those errors are. Sorry I’ve no idea how ofw works on a mac.

for mac includes you’ll have to do it like we do it in qtutils.h :

  
  
#if TARGET_OS_MAC  
	#include <Quicktime/QuickTime.h>  
	#include <CoreServices/CoreServices.h>  
	#include <ApplicationServices/ApplicationServices.h>  
#else  
	#include <QTML.h>  
	#include <FixMath.h>  
	#include <QuickTimeComponents.h>  
	#include <TextUtils.h>	  
#endif  
  

since windows / mac includes quicktime differently (on mac it’s a framework). If there are missing includes (this above is for playing and capturing) just google around and find the files they are in, and figure out the mac-ish way of adding them.

also, I think there may be some pc specific stuff relating to native file paths. I don’t think it will work out of the box but with some tinkering (especially as relates to saving etc) I think it’d work.

good luck!
zach

I’m getting the following error

  
  
error: 'io_user_reference_t' was not declared in this scope  
  

when compiling “OSMessageNotification.h”, which is called by “Carbon.h”, which is called by “QuickTime.h”. I did a quick search and found that “io_user_reference_t” is defined in “device_types.h”, which is included at the top of “OSMessageNotification.h”.

I’m guessing this is more of that header voodoo playing tricks on me, but I don’t know enough about C++ to guess what to do next. Any ideas?

I’m not on a mac – so take what I say with a grain of salt, but I’d try building a project from a working sample code again – it looks like you might have gotten some other quicktime stuff in there somehow, and there might be incompatibilities.

if other OF code works (movie player, etc) then you should be able to compile against quicktime without problems.

if it’s still a problem, I’d try adding additional headers (with no code) one by one till you see what the problem is…

always recommended is moving slowly from something that works, step by step…

good luck!
zach

Hey,

I started again from scratch and that error mysteriously disappeared so I was able to get the movie recorder working (kind of).

I got rid of the “saveViaFileDialog()” function for now, and modified “save(char * fileName)”, replacing

  
  
   //-------------------------------  
	// we need a full path here to get an FSSpec:  
	//  
	char cwdir[MAX_PATH];  
	_getcwd(cwdir, _MAX_PATH);  
	char buffer[MAX_PATH];  
	sprintf(buffer, "%s//%s",  cwdir, fileName);  
	// mac might be different then this:  
	NativePathNameToFSSpec (buffer, &fss, 0);  
  

with

  
  
   //-------------------------------  
	// we need a full path here to get an FSSpec:  
	//  
   char cwdir[MAX_PATH];  
	char buffer[MAX_PATH];  
	  
#if TARGET_OS_WIN32  
	_getcwd(cwdir, _MAX_PATH);  
	sprintf(buffer, "%s//%s",  cwdir, fileName);  
	// mac might be different then this:  
	NativePathNameToFSSpec (buffer, &fss, 0);  
#else  
   getcwd(cwdir, MAX_PATH);  
	sprintf(buffer, "%s/%s",  cwdir, ofToDataPath(fileName).c_str());  
      
   FSRef fsref;  
   Boolean isdir = false;  
      
   result = FSPathMakeRef((const UInt8*)buffer, &fsref, &isdir);  
   if (result) {   
       printf("FSPathMakeRef failed %d\n", result);   
       printf("ERROR SAVING movie \n");   
       return;  
   }  
   result = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fss, NULL);  
   if (result) {   
       printf("FSGetCatalogInfo failed %d\n", result);   
       printf("ERROR SAVING movie \n");   
       return;   
   }  
  
#endif  
  

Now the tricky thing is that this only works if the .MOV file already exists in at the specified path. If not, I get

  
  
FSPathMakeRef failed -43  
  

in the console.

Hi guys - very useful thread. I’m looking to do something very similar and this code has helped enormously so thanks :slight_smile:

Only problem is that when saving out there is a thick black border on the right hand side and the image is squeezed into the left hand side. When using a 640x480 webcam feed the image is only 480 wide with a 160 wide black block to the right of it.

I’ve tried it on both Mac Leopard and Win XP and its the same issue. Any suggestions would be massively appreciated.

thanks
Gareth

Silly error really. I was converting an image using just the RGB pixels when it should have been RGBA.

cheers

prisoner john –

I’ve been relooking at saving quicktime, this time directly to disk and discovered that if the file doesn’t exit you need to create it. I delved into the apple documentation and found it too hard to get into, so I just used std c style file creation and it should solve your problem:

  
  
	#ifdef TARGET_OSX  
	  
		/// kill a file and make a new one if needed:		  
		FILE * pFile;  
		pFile = fopen (pszFilename,"w");  
		fclose (pFile);  
	  
		Boolean isdir;  
		osErr = FSPathMakeRef((const UInt8*)pszFilename, &fsref, &isdir);  
		printf("%i \n", osErr);  
		  
		osErr = FSGetCatalogInfo(&fsref, kFSCatInfoNone, NULL, NULL, &fsSpec, NULL);  
		printf("%i \n", osErr);  
	#endif  
  

that should, I think, solve your issue of needing the file to exist before you save…

take care!
zach

Hey Zach, I had that problem too but called a shell script which used the touch command to create the file.

I needed to blend a bunch of movies to leave a trace of history in the final movie and found QTCoffee did the trick - again from a shell script.

If anyone hasn’t come across QTCoffee its well worth looking at as it makes non-selfcontained movies. The benefit is that there is no need to re-render anything as the non-selfcontained movie contains reference to other movies.

Best bit is it is free. Unfortunately its Mac only.

cheers

Hi Gareth -

thanks! those are some good tricks to know about. I didn’t at all think about scripting :slight_smile:

I’ve uploaded some example code of saving directly to disk (instead of to ram) that should work pretty well :

http://www.openframeworks.cc/files/vide-…-sk-src.zip

it does the fopen trick to make a new file and seems to fine on mac/pc

take care -
zach

Hey this works perfectly. Using the Animation codec, I barely even notice a drop in framerate for my project.

One thing I couldnt get to work is calling setup again after finishMovie in order to record a new video. it would either corrupt the output or crash the program.

Great work!

hmm – can you try a much shorter file name? I just tested and it seems to crash with longer filenames or longer path names… I am looking for a solution…

http://lists.apple.com/archives/QuickTi-…-00076.html

http://lists.apple.com/archives/QuickTi-…-00071.html

http://lists.apple.com/archives/QuickTi-…-00085.html

take care
zach