Skip to content

Commit

Permalink
Merge pull request #132 from JonnyBurger/puppeteer-support
Browse files Browse the repository at this point in the history
  • Loading branch information
JonnyBurger committed Mar 2, 2021
2 parents 5430e37 + f27602d commit a64387d
Show file tree
Hide file tree
Showing 21 changed files with 7,942 additions and 13,485 deletions.
43 changes: 40 additions & 3 deletions packages/cli/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 11 additions & 1 deletion packages/cli/src/parse-command-line.ts
@@ -1,7 +1,14 @@
import minimist from 'minimist';
import {Codec, Config, ImageFormat, PixelFormat} from 'remotion';
import {
BrowserExecutable,
Codec,
Config,
ImageFormat,
PixelFormat,
} from 'remotion';

export type CommandLineOptions = {
['browser-executable']: BrowserExecutable;
['pixel-format']: PixelFormat;
['image-format']: ImageFormat;
concurrency: number;
Expand All @@ -25,6 +32,9 @@ export const parseCommandLine = () => {
if (parsedCli['image-format']) {
Config.Rendering.setImageFormat(parsedCli['image-format']);
}
if (parsedCli['browser-executable']) {
Config.Puppeteer.setBrowserExecutable(parsedCli['browser-executable']);
}
if (parsedCli.concurrency) {
Config.Rendering.setConcurrency(parsedCli.concurrency);
}
Expand Down
41 changes: 30 additions & 11 deletions packages/cli/src/render.tsx
@@ -1,5 +1,6 @@
import {bundle} from '@remotion/bundler';
import {
ensureLocalBrowser,
ffmpegHasFeature,
getActualConcurrency,
getCompositions,
Expand Down Expand Up @@ -77,6 +78,7 @@ export const render = async () => {
const overwrite = Internals.getShouldOverwrite();
const userProps = getUserProps();
const quality = Internals.getQuality();
const browser = Internals.getBrowser() ?? Internals.DEFAULT_BROWSER;

const absoluteOutputFile = path.resolve(process.cwd(), outputFile);
if (fs.existsSync(absoluteOutputFile) && !overwrite) {
Expand All @@ -102,6 +104,13 @@ export const render = async () => {
pixelFormat,
imageFormat
);
try {
await ensureLocalBrowser(browser);
} catch (err) {
console.error('Could not download a browser for rendering frames.');
console.error(err);
process.exit(1);
}
if (shouldOutputImageSequence) {
fs.mkdirSync(absoluteOutputFile, {
recursive: true,
Expand All @@ -123,10 +132,12 @@ export const render = async () => {
const bundled = await bundle(fullPath, (progress) => {
bundlingProgress.update(progress);
});
const comps = await getCompositions(bundled);
const compositionId = getCompositionId(comps);

bundlingProgress.stop();
const comps = await getCompositions(
bundled,
Internals.getBrowser() ?? Internals.DEFAULT_BROWSER
);
const compositionId = getCompositionId(comps);

const config = comps.find((c) => c.id === compositionId);
if (!config) {
Expand Down Expand Up @@ -164,6 +175,7 @@ export const render = async () => {
webpackBundle: bundled,
imageFormat,
quality,
browser,
});
renderProgress.stop();
if (process.env.DEBUG) {
Expand Down Expand Up @@ -201,14 +213,21 @@ export const render = async () => {
stitchingProgress.stop();

console.log('Cleaning up...');
await Promise.all([
fs.promises.rmdir(outputDir, {
recursive: true,
}),
fs.promises.rmdir(bundled, {
recursive: true,
}),
]);
try {
await Promise.all([
fs.promises.rmdir(outputDir, {
recursive: true,
}),
fs.promises.rmdir(bundled, {
recursive: true,
}),
]);
} catch (err) {
console.error('Could not clean up directory.');
console.error(err);
console.log('Do you have minimum required Node.js version?');
process.exit(1);
}
console.log('\n▶️ Your video is ready - hit play!');
} else {
console.log('\n▶️ Your image sequence is ready!');
Expand Down
13 changes: 13 additions & 0 deletions packages/core/src/config/browser-executable.ts
@@ -0,0 +1,13 @@
export type BrowserExecutable = string | null;

let currentBrowserExecutablePath: BrowserExecutable = null;

export const setBrowserExecutable = (
newBrowserExecutablePath: BrowserExecutable
) => {
currentBrowserExecutablePath = newBrowserExecutablePath;
};

export const getBrowserExecutable = () => {
return currentBrowserExecutablePath;
};
24 changes: 24 additions & 0 deletions packages/core/src/config/browser.ts
@@ -0,0 +1,24 @@
export type Browser = 'chrome' | 'firefox';

export const DEFAULT_BROWSER: Browser = 'chrome';

// There is no Firefox support yet, the waitForFunction method
// does not yet work and downloading has a bug.
// Disabling this for now!
export const FEATURE_FLAG_FIREFOX_SUPPORT = false;

let currentBrowser: Browser | null = null;

export const setBrowser = (browser: Browser) => {
if (browser === 'chrome') {
process.env.PUPPETEER_PRODUCT = 'chrome';
}
if (browser === 'firefox') {
process.env.PUPPETEER_PRODUCT = 'firefox';
}
currentBrowser = browser;
};

export const getBrowser = () => {
return currentBrowser;
};
14 changes: 12 additions & 2 deletions packages/core/src/config/index.ts
@@ -1,3 +1,5 @@
import {Browser} from './browser';
import {BrowserExecutable, setBrowserExecutable} from './browser-executable';
import {Codec, setCodec, setOutputFormat} from './codec';
import {Concurrency, setConcurrency} from './concurrency';
import {setCrf} from './crf';
Expand All @@ -21,6 +23,13 @@ export const Config = {
*/
overrideWebpackConfig,
},
Puppeteer: {
/**
* Specify executable path for the browser to use.
* Default: null, which will make Remotion find or download a version of said browser.
*/
setBrowserExecutable,
},
Rendering: {
/**
* Sets how many Puppeteer instances will work on rendering your video in parallel.
Expand All @@ -34,8 +43,7 @@ export const Config = {
* Default: 80
*/
setQuality,
/**
* Decide in which image format to render. Can be either 'jpeg' or 'png'.
/** Decide in which image format to render. Can be either 'jpeg' or 'png'.
* PNG is slower, but supports transparency.
*/
setImageFormat,
Expand Down Expand Up @@ -80,6 +88,8 @@ export type {
Concurrency,
WebpackConfiguration,
WebpackOverrideFn,
BrowserExecutable,
ImageFormat,
Codec,
Browser,
};
10 changes: 10 additions & 0 deletions packages/core/src/internals.ts
Expand Up @@ -4,6 +4,12 @@ import {
TComposition,
TSequence,
} from './CompositionManager';
import {
DEFAULT_BROWSER,
FEATURE_FLAG_FIREFOX_SUPPORT,
getBrowser,
} from './config/browser';
import {getBrowserExecutable} from './config/browser-executable';
import {
DEFAULT_CODEC,
getFinalOutputCodec,
Expand Down Expand Up @@ -48,6 +54,7 @@ export const Internals = {
RemotionRoot,
useVideo,
getRoot,
getBrowserExecutable,
getCompositionName,
getIsEvaluation,
getPixelFormat,
Expand All @@ -61,6 +68,9 @@ export const Internals = {
getFinalOutputCodec,
DEFAULT_CODEC,
DEFAULT_PIXEL_FORMAT,
FEATURE_FLAG_FIREFOX_SUPPORT,
getBrowser,
DEFAULT_BROWSER,
getDefaultCrfForCodec,
getActualCrf,
getUserPreferredImageFormat,
Expand Down
1 change: 1 addition & 0 deletions packages/docs/docs/cli.md
Expand Up @@ -23,6 +23,7 @@ Besides choosing a video and output location with the command line arguments, th
- `--sequence`: [Pass this flag if you want an image sequence as the output instead of a video.](config#setimagesequence) Available since v1.4.
- `--codec`: [`h264` or `h265` or `png` or `vp8` or `vp9`](config#setoutputformat). If you don't supply `--codec`, it will use the H.264 encoder. Available since v1.4.
- `--crf`: [To set Constant Rate Factor (CRF) of the output](config#setcrf). Minimum 0. Use this rate control mode if you want to keep the best quality and care less about the file size. Available since v1.4.
- `--browser-executable`: [Path to a Chrome executable](config#setbrowserexecutable). If not specified and Remotion cannot find one, it will download one during rendering. Available since v1.5.

:::info
If you don't feel like passing command line flags every time, consider creating a `remotion.config.ts` [config file](config).
Expand Down
12 changes: 12 additions & 0 deletions packages/docs/docs/config.md
Expand Up @@ -27,6 +27,18 @@ Config.Bundling.overrideWebpackConfig((currentConfiguration) => {
});
```

## Puppeteer

### setBrowserExecutable()

Set a custom Chrome or Chromium executable path. By default Remotion will try to find an existing version of Chrome on your system and if not found, it will download one. This flag is useful if you don't have Chrome installed in a standard location and you want to prevent downloading an additional browser or need [support for the H264 codec](/docs/video#codec-support).

```ts
Config.Puppeteer.setBrowserExecutable('/usr/bin/google-chrome-stable')
```

The [command line flag](cli) `--browser-executable` will take precedence over this option.

## Rendering

### setConcurrency()
Expand Down
12 changes: 12 additions & 0 deletions packages/docs/docs/getting-started.md
Expand Up @@ -29,3 +29,15 @@ npm init video
```

That's it! Wait for the installation to be finished and follow the instructions in the terminal.

### Additional step for Linux users

Linux users need to install some additional packages to get Chrome/Puppeteer working correctly.

**Ubuntu**

```console
apt install -y gconf-service libasound2 libatk1.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget libgbm-dev
```

Got instructions for more Linux distributions? [Add them to this page](https://github.com/JonnyBurger/remotion/edit/main/packages/docs/docs/getting-started.md)!
6 changes: 2 additions & 4 deletions packages/docs/docs/importing-assets.md
Expand Up @@ -6,7 +6,7 @@ title: Importing assets
Remotion allows you to include several types of files in your project:

- Images (`.png`, `.svg`, `.jpg`, `.jpeg`, `.webp`, `.gif`, `.bmp`)
- Videos (`.webm`, `.mp4`), with constraints
- Videos (`.webm`, `.mp4`)
- Audio (`.mp3`, `.wav`, `.aac`), preview only
- [Fonts (`.woff` and `.woff2`) - read the separate page for fonts](fonts)

Expand Down Expand Up @@ -69,9 +69,7 @@ export const MyComp: React.FC = () => {
}
```

:::info
Since Puppeteer doesn't include the proprietary codec to read MP4 videos, you must convert your videos to WebM before rendering.
:::
Be aware that if you are rendering using Chromium (as opposed to Chrome), the codec for MP4 videos is not included. Read the section on the [`<Video/ >`](/docs/video#codec-support) page for more information.

## Using Audio

Expand Down

0 comments on commit a64387d

Please sign in to comment.