From a8db19fa2bc987cf421e59c80092edbd47dff8b3 Mon Sep 17 00:00:00 2001 From: Matthew Hutchinson Date: Tue, 26 Oct 2021 22:38:00 +0100 Subject: [PATCH] Ctrl+z pause/resumes, prep README/CHANGELOG --- CHANGELOG.md | 10 +++++++++- README.md | 19 ++++++++++--------- videosnap/Constants.m | 2 +- videosnap/VideoSnap.h | 20 +++++++++++++------- videosnap/main.m | 20 ++++++++++++++++---- videosnap/videosnap.1 | 3 ++- videosnap/videosnap.m | 22 +++++++++++++++++----- 7 files changed, 68 insertions(+), 28 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 390b05b..b373554 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,13 @@ adheres to [Semantic Versioning](Semver). - Your contribution here! +## [0.0.8] - 2020-Oct-27 +### Added +- Ctrl+z to pause/resume capture + +### Changed +- Default filename postfixed with timestamp + ## [0.0.7] - 2020-Oct-19 ### Added - Fix issues with connected iOS device discovery and build/test on M1 arch @@ -58,7 +65,8 @@ adheres to [Semantic Versioning](Semver). ### Changed - Initial release (using the QTKit framework) -[Unreleased]: https://github.com/matthutchinson/videosnap/compare/v0.0.7...HEAD +[Unreleased]: https://github.com/matthutchinson/videosnap/compare/v0.0.8...HEAD +[0.0.8]: https://github.com/matthutchinson/videosnap/compare/v0.0.7...v0.0.8 [0.0.7]: https://github.com/matthutchinson/videosnap/compare/v0.0.5...v0.0.7 [0.0.5]: https://github.com/matthutchinson/videosnap/compare/v0.0.4...v0.0.5 [0.0.4]: https://github.com/matthutchinson/videosnap/compare/v0.0.3...v0.0.4 diff --git a/README.md b/README.md index 5f954d1..957d40f 100644 --- a/README.md +++ b/README.md @@ -1,23 +1,25 @@ # VideoSnap VideoSnap is an macOS command line tool for recording video and audio from any -attached capture device (including any attached iOS device). +attached capture device (including screen capture from connected iOS devices). -You can specify which device to capture from, the duration, encoding and a delay -period (before capturing starts). You can also disable audio recording. +You can specify which device to capture from (by device name), the duration, +encoding and a delay period (before capturing starts). By default VideoSnap will capture both video and audio from the default capture device at 30fps, with a Medium quality preset and a short (0.5s) warm-up delay. If no duration is specified, VideoSnap will record until you cancel with -[Ctrl+c]. You can also use VideoSnap to list attached capture devices by name. +[Ctrl+c] or you can pause (and resume) recording with [Ctrl+z]. + +VideoSnap can list attached capture devices by name. ## Requirements * macOS 10.9+ (Intel/M1) - * A web cam + * A web cam or iOS device -If you need to capture video on older versions of macOS (e.g. 32-bit) try +If you need to capture video on older versions of macOS (e.g. 32-bit OSX) try [wacaw](http://webcam-tools.sourceforge.net) ## Installation @@ -84,9 +86,9 @@ Use the `-p` flag to choose a preset. ### Capturing from connected iOS devices -It is possible to screen capture video & audio from an attached iOS device. +It is possible to screen capture video & audio from an attached iOS device. -For the device to be discovered you must confirm that you +For the device to be discovered you must confirm that you **Trust This Computer** on the device when it is connected and unlocked. There are some limitations and issues with iOS screen capturing. @@ -166,7 +168,6 @@ If you'd like to get involved in contributing, here are some ideas: * Allow VideoSnap to pipe captured bytes to the STDOUT stream * Submit VideoSnap as a package for [Homebrew](http://brew.sh) -* Default filename should include a timestamp of when recording began * Allow more size/quality options for video and/or audio * Smile detection while capturing video/image, determine a happiness factor/score * Allow VideoSnap to capture a single frame to an image file (with compression diff --git a/videosnap/Constants.m b/videosnap/Constants.m index d65729f..4785e03 100644 --- a/videosnap/Constants.m +++ b/videosnap/Constants.m @@ -10,7 +10,7 @@ NSString *const VERSION = @"0.0.8"; -int const DEFAULT_FRAMES_PER_SECOND = 30; +int const DEFAULT_FRAMES_PER_SECOND = 30; float const DEFAULT_RECORDING_DELAY = 0.5; NSString *const DEFAULT_ENCODING_PRESET = @"Medium"; diff --git a/videosnap/VideoSnap.h b/videosnap/VideoSnap.h index c8aed63..b7a215a 100644 --- a/videosnap/VideoSnap.h +++ b/videosnap/VideoSnap.h @@ -12,16 +12,18 @@ // logging #define error(...) fprintf(stderr, __VA_ARGS__) -#define console(...) printf(__VA_ARGS__) -#define verbose(...) (self->isVerbose && fprintf(stderr, __VA_ARGS__)) +#define console(...) fprintf(stdout, __VA_ARGS__) +#define verbose(...) (self->isVerbose && fprintf(stdout, __VA_ARGS__)) #define verbose_error(...) (self->isVerbose && fprintf(stderr, __VA_ARGS__)) // VideoSnap @interface VideoSnap : NSObject { - AVCaptureSession *session; + AVCaptureSession *session; + AVCaptureConnection *conn; AVCaptureMovieFileOutput *movieFileOutput; - NSMutableArray *connectedDevices; - BOOL isVerbose; + NSMutableArray *connectedDevices; + BOOL isVerbose; + NSString *filePath; } // @@ -62,7 +64,6 @@ */ -(void)listConnectedDevices; - /** * Get default generated filename */ @@ -89,7 +90,12 @@ * * @return BOOL */ --(BOOL)startSession:(AVCaptureDevice *)device filePath:(NSString *)path recordingDuration:(NSNumber *)recordSeconds encodingPreset:(NSString *)encodingPreset delaySeconds:(NSNumber *)delaySeconds noAudio:(BOOL)noAudio; +-(BOOL)startSession:(AVCaptureDevice *)device recordingDuration:(NSNumber *)recordSeconds encodingPreset:(NSString *)encodingPreset delaySeconds:(NSNumber *)delaySeconds noAudio:(BOOL)noAudio; + +/** + * Delegates togglePauseRecording to movieFileOutput, with SIGINT value from handler + */ + -(void)togglePauseRecording:(int)sigNum; /** * Adds an audio device to the capture session, uses the audio from chosen video device diff --git a/videosnap/main.m b/videosnap/main.m index f203f27..31a8430 100644 --- a/videosnap/main.m +++ b/videosnap/main.m @@ -15,7 +15,7 @@ VideoSnap *videoSnap; /** - * signal interrupt handler + * signal interrupt handler Ctrl+c */ void SIGINT_handler(int signum) { if (!isInterrupted && [videoSnap isRecording]) { @@ -26,15 +26,26 @@ void SIGINT_handler(int signum) { } } +/** + * signal interrupt handler Ctrl+z + */ +void SIGSTP_handler(int signum) { + if ([videoSnap isRecording]) { + [videoSnap togglePauseRecording:signum]; + } +} + /** * main */ int main(int argc, const char * argv[]) { - isInterrupted = NO; - // setup int handler for Ctrl+C cancelling + // setup int handlers + // Ctrl+C cancels + // Ctrl+Z pause/resume signal(SIGINT, &SIGINT_handler); + signal(SIGTSTP, &SIGSTP_handler); // C args as NSArray NSMutableArray *args = [[NSMutableArray alloc] initWithCapacity: argc]; @@ -42,7 +53,8 @@ int main(int argc, const char * argv[]) { [args addObject: [NSString stringWithCString: argv[i] encoding: NSUTF8StringEncoding]]; } - videoSnap = [[VideoSnap alloc] initWithVerbosity:([args indexOfObject:@"-v"] != NSNotFound)]; + videoSnap = [[VideoSnap alloc] + initWithVerbosity:([args indexOfObject:@"-v"] != NSNotFound)]; return [videoSnap processArgs: args]; } diff --git a/videosnap/videosnap.1 b/videosnap/videosnap.1 index ac85382..9dc1ae1 100644 --- a/videosnap/videosnap.1 +++ b/videosnap/videosnap.1 @@ -25,6 +25,7 @@ videosnap will capture video and audio from the first found device at 30fps with a Medium quality preset and a short (0.5s) warm-up delay. .Pp If no duration is specified, videosnap will record until you cancel with [Ctrl+c] +You can pause (and resume) recording with [Ctrl+z]. .Pp You can also use .Nm @@ -76,7 +77,7 @@ No known bugs. Please report any issues here: https://github.com/matthutchinson/ .Sh HISTORY \" Document history if command behaves in a unique manner .Bl -tag -width -indent .It 0.0.8 -2021-Oct-25 Default filename now includes a date/time stamp +2021-Oct-27 Default filename postfixed with timestamp, Ctrl+z to pause/resume capture .It 0.0.7 2021-Oct-18 Fix issues with connected iOS device discovery and build/test on M1 arch .It 0.0.6 diff --git a/videosnap/videosnap.m b/videosnap/videosnap.m index ca7c3dd..5041bbc 100644 --- a/videosnap/videosnap.m +++ b/videosnap/videosnap.m @@ -62,7 +62,6 @@ - (int)processArgs:(NSArray *)arguments { // argument defaults AVCaptureDevice *device; - NSString *filePath; NSString *encodingPreset = DEFAULT_ENCODING_PRESET; NSNumber *delaySeconds = [NSNumber numberWithFloat:DEFAULT_RECORDING_DELAY]; NSNumber *recordingDuration = nil; @@ -177,7 +176,6 @@ - (int)processArgs:(NSArray *)arguments { // start capturing video, start a run loop if ([self startSession:device - filePath:filePath recordingDuration:recordingDuration encodingPreset:encodingPreset delaySeconds:delaySeconds @@ -186,7 +184,7 @@ - (int)processArgs:(NSArray *)arguments { if(recordingDuration != nil) { console("Started capture...\n"); } else { - console("Started capture (ctrl+c to stop)...\n"); + console("Started capture (ctrl+c to stop, ctrl+z to pause) ...\n"); } [[NSRunLoop currentRunLoop] run]; } else { @@ -299,7 +297,6 @@ - (AVCaptureDevice *)deviceNamed:(NSString *)name { * Start a capture session on a device, saving to filePath for recordSeconds */ - (BOOL)startSession:(AVCaptureDevice *)videoDevice - filePath:(NSString *)filePath recordingDuration:(NSNumber *)recordingDuration encodingPreset:(NSString *)encodingPreset delaySeconds:(NSNumber *)delaySeconds @@ -344,7 +341,7 @@ - (BOOL)startSession:(AVCaptureDevice *)videoDevice // set capture frame rate (fps) int32_t fps = DEFAULT_FRAMES_PER_SECOND; verbose("(set capture framerate to %i fps)\n", fps); - AVCaptureConnection *conn = [movieFileOutput connectionWithMediaType:AVMediaTypeVideo]; + conn = [movieFileOutput connectionWithMediaType:AVMediaTypeVideo]; if([conn isVideoMinFrameDurationSupported]) { conn.videoMinFrameDuration = CMTimeMake(1, fps); } @@ -417,6 +414,21 @@ - (BOOL)startSession:(AVCaptureDevice *)videoDevice return success; } +/** + * Toggle pause/resume recording to the file + */ +- (void)togglePauseRecording:(int)sigNum { + verbose("\n(caught signal: [%d])\n", sigNum); + + if([movieFileOutput isRecordingPaused]) { + fprintf(stderr, "\nResuming capture ...\n"); + [movieFileOutput resumeRecording]; + } else { + fprintf(stderr, "\nPausing capture ... (ctrl+z to resume, ctrl+c to stop)\n"); + [movieFileOutput pauseRecording]; + } +} + /** * Adds an audio device to the capture session, from video device or first available */