🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

aperture

Package Overview
Dependencies
Maintainers
3
Versions
23
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

aperture - npm Package Compare versions

Comparing version

to
2.1.0

117

index.js

@@ -0,38 +1,63 @@

'use strict';
const os = require('os');
const util = require('util');
const path = require('path');
const execa = require('execa');
const tmp = require('tmp');
// TODO: log in production with proces.env.DEBUG_APERTURE
function log(...msgs) {
if (process.env.DEBUG) {
console.log(...msgs);
const debuglog = util.debuglog('aperture');
const isYosemiteOrHigher = process.platform === 'darwin' && Number(os.release().split('.')[0]) >= 14;
class Aperture {
constructor() {
if (!isYosemiteOrHigher) {
throw new Error('Requires macOS 10.10 or higher');
}
}
}
class Aperture {
getAudioSources() {
return execa(path.join(__dirname, 'swift', 'main'), ['list-audio-devices']).then(result => {
return JSON.parse(result.stdout);
});
return execa.stdout(path.join(__dirname, 'swift/main'), ['list-audio-devices']).then(JSON.parse);
}
// resolves if the recording started successfully
// rejects if the recording didn't started after 5 seconds or if some error
// occurs during the recording session
startRecording({
fps = 30,
cropArea = 'none', // can be 'none' or {x, y, width, height} – TODO: document this
cropArea = 'none',
showCursor = true,
highlightClicks = false,
displayId = 'main',
audioSourceId = 'none' // one of the `id`s from getAudioSources()
audioSourceId = 'none'
} = {}) {
return new Promise((resolve, reject) => {
if (this.recorder !== undefined) {
reject(new Error('Call `.stopRecording()` first'));
return;
}
if (highlightClicks === true) {
showCursor = true;
}
this.tmpPath = tmp.tmpNameSync({postfix: '.mp4'});
if (typeof cropArea === 'object') { // TODO validate this
if (typeof cropArea === 'object') {
if (typeof cropArea.x !== 'number' ||
typeof cropArea.y !== 'number' ||
typeof cropArea.width !== 'number' ||
typeof cropArea.height !== 'number') {
reject(new Error('Invalid `cropArea` option object'));
return;
}
cropArea = `${cropArea.x}:${cropArea.y}:${cropArea.width}:${cropArea.height}`;
}
const recorderOpts = [this.tmpPath, fps, cropArea, showCursor, highlightClicks, displayId, audioSourceId];
const recorderOpts = [
this.tmpPath,
fps,
cropArea,
showCursor,
highlightClicks,
displayId,
audioSourceId
];

@@ -42,16 +67,25 @@ this.recorder = execa(path.join(__dirname, 'swift', 'main'), recorderOpts);

const timeout = setTimeout(() => {
const err = new Error('unnable to start the recorder after 5 seconds');
// `.stopRecording()` was called already
if (this.recorder === undefined) {
return;
}
const err = new Error('Could not start recording within 5 seconds');
err.code = 'RECORDER_TIMEOUT';
this.recorder.kill();
delete this.recorder;
reject(err);
}, 5000);
this.recorder.catch(err => {
clearTimeout(timeout);
delete this.recorder;
reject(err.stderr ? new Error(err.stderr) : err);
});
this.recorder.stdout.setEncoding('utf8');
this.recorder.stdout.on('data', data => {
data = data.toString();
debuglog(data);
log(data);
if (data.replace(/\n|\s/gm, '') === 'R') {
if (data.trim() === 'R') {
// `R` is printed by Swift when the recording **actually** starts

@@ -62,17 +96,2 @@ clearTimeout(timeout);

});
this.recorder.on('error', reject); // TODO handle this;
this.recorder.on('exit', code => {
clearTimeout(timeout);
let err;
if (code === 0) {
return; // we're good
} else if (code === 1) {
err = new Error('malformed arguments'); // TODO
} else if (code === 2) {
err = new Error('invalid coordinates'); // TODO
} else {
err = new Error('unknown error'); // TODO
}
reject(err);
});
});

@@ -84,17 +103,11 @@ }

if (this.recorder === undefined) {
reject('call `startRecording` first');
reject(new Error('Call `.startRecording()` first'));
return;
}
this.recorder.on('exit', code => {
// at this point the movie file has been fully written to the file system
if (code === 0) {
delete this.recorder;
resolve(this.tmpPath);
// TODO: this file is deleted when the program exits
// maybe we should add a note about this on the docs or implement a workaround
delete this.tmpPath;
} else {
reject(code); // TODO
}
this.recorder.then(() => {
delete this.recorder;
resolve(this.tmpPath);
}).catch(err => {
reject(err.stderr ? new Error(err.stderr) : err);
});

@@ -101,0 +114,0 @@

{
"name": "aperture",
"version": "2.0.0",
"version": "2.1.0",
"description": "Record the screen on macOS",

@@ -8,9 +8,23 @@ "license": "MIT",

"author": "Matheus Fernandes <npm@matheus.top> (https://matheus.top)",
"maintainers": [
{
"name": "Sindre Sorhus",
"email": "sindresorhus@gmail.com",
"url": "sindresorhus.com"
}
],
"engines": {
"node": ">=6"
},
"scripts": {
"test": "xo",
"build": "cd swift && xcodebuild && mv build/release/aperture main && rm -r build",
"build": "cd swift && xcodebuild -derivedDataPath $(mktemp -d) -scheme aperture",
"prepublish": "npm run build"
},
"files": [
"index.js",
"swift/main"
],
"dependencies": {
"execa": "^0.5.0",
"execa": "^0.6.0",
"tmp": "0.0.31"

@@ -21,6 +35,2 @@ },

},
"files": [
"index.js",
"swift/main"
],
"xo": {

@@ -27,0 +37,0 @@ "space": true,

<p>
<h1 align="center">aperture</h1>
<h3 align="center">A library for screen recording </h3>
<h1 align="center">Aperture</h1>
<h4 align="center">Record the screen on macOS</h4>
<p align="center"><a href="https://github.com/sindresorhus/xo"><img src="https://img.shields.io/badge/code_style-XO-5ed9c7.svg" alt="XO code style"></a></p>
</p>
## Install
```
npm install aperture
$ npm install aperture
```
*Requires macOS 10.10 or later.*
## Usage
```javascript
```js
const aperture = require('aperture')();
const cropArea = {x: 100, y: 100, width: 500, height: 500};
const options = {
fps: 30,
cropArea: {
x: 100,
y: 100,
width: 500,
height: 500
}
};
aperture.startRecording({fps: 30, cropArea})
.then(filePath => setTimeout(stopRecording, 3000));
aperture.startRecording(options).then(filePath => {
setTimeout(() => {
aperture.stopRecording().then(console.log);
//=> '/var/folders/r9/65knbqts47x3yg055cd739qh0000gn/T/tmp-15694AAzbYX1vzi2X.mp4'
}, 3000);
});
```
function stopRecording() {
aperture.stopRecording()
.then(console.log); //=> /var/folders/r9/65knbqts47x3yg055cd739qh0000gn/T/tmp-15694AAzbYX1vzi2X.mp4
}
```
## API

@@ -36,7 +47,9 @@

Returns a promise for the path to the screen recording file.
Returns a `Promise` for the path to the screen recording file.
Fullfills when the recording starts or rejects if the recording didn't start after 5 seconds.
### instance.stopRecording()
Returns a promise for the path to the screen recording file.
Returns a `Promise` for the path to the screen recording file.

@@ -86,2 +99,4 @@ ### instance.getAudioSources()

Enabling this will also enable the `showCursor` option.
##### displayId

@@ -104,4 +119,3 @@

`aperture` was built to fulfill the needs of [Kap](https://github.com/wulkano/kap), providing a JavaScript interface to the **best** available method for recording the screen.
That's why it's currently a wrapper for a [Swift script](https://github.com/wulkano/aperture/blob/master/swift/aperture/main.swift) that records the screen using the [AVFoundation framework](https://developer.apple.com/av-foundation/).
Aperture was built to fulfill the needs of [Kap](https://github.com/wulkano/kap), providing a JavaScript interface to the **best** available method for recording the screen. That's why it's currently a wrapper for a [Swift script](https://github.com/wulkano/aperture/blob/master/swift/aperture/main.swift) that records the screen using the [AVFoundation framework](https://developer.apple.com/av-foundation/).

@@ -120,8 +134,10 @@ #### But you can use `ffmpeg -f avfoundation...`

## Linux and Windows
We want to bring `aperture` to Linux and Windows, but we don't have time and resources for such tasks (we're Mac users), so **any help is more than welcome**. We just want to enforce two things: **performance** and **quality** – it doesn't matter how (`ffmpeg`, custom built native lib, etc) they are achieved.
We want to bring Aperture to Linux and Windows, but we don't have time or resources for such tasks (we're Mac users), so **any help is more than welcome**. We just want to enforce two things: **performance** and **quality** – it doesn't matter how (`ffmpeg`, custom built native lib, etc) they are achieved.
## Upcoming
`aperture` is in its early days. We're working on adding more features, such as *export to GIF*, compression options, support for multiple displays, support for audio and much more. Check out our [`aperture`](https://github.com/wulkano/kap/issues?q=is%3Aissue+is%3Aopen+label%3Aaperture) issues on **Kap** to learn more.
Aperture is in its early days. We're working on adding more features, such as *export to GIF*, compression options, support for multiple displays, support for audio, and much more. Check out our [Aperture](https://github.com/wulkano/kap/issues?q=is%3Aissue+is%3Aopen+label%3Aaperture) issues on **Kap** to learn more.

Sorry, the diff of this file is not supported yet