@remotion/renderer 3.3.61 → 3.3.62

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,9 @@
1
1
  import type { MediaAsset } from './assets/types';
2
+ import type { FilterWithoutPaddingApplied } from './stringify-ffmpeg-filter';
2
3
  export declare const calculateFfmpegFilter: ({ asset, fps, durationInFrames, channels, assetDuration, }: {
3
4
  asset: MediaAsset;
4
5
  fps: number;
5
6
  durationInFrames: number;
6
7
  channels: number;
7
8
  assetDuration: number | null;
8
- }) => string | null;
9
+ }) => FilterWithoutPaddingApplied | null;
@@ -1,5 +1,15 @@
1
1
  import type { DownloadMap } from './assets/download-map';
2
- export declare const createFfmpegComplexFilter: (filters: number, downloadMap: DownloadMap) => Promise<{
3
- complexFilterFlag: [string, string] | null;
2
+ import type { FfmpegExecutable } from './ffmpeg-executable';
3
+ import type { PreprocessedAudioTrack } from './preprocess-audio-track';
4
+ export declare const createFfmpegComplexFilter: ({ filters, downloadMap, ffmpegExecutable, remotionRoot, }: {
5
+ filters: PreprocessedAudioTrack[];
6
+ downloadMap: DownloadMap;
7
+ ffmpegExecutable: FfmpegExecutable;
8
+ remotionRoot: string;
9
+ }) => Promise<{
10
+ complexFilterFlag: [
11
+ string,
12
+ string
13
+ ] | null;
4
14
  cleanup: () => void;
5
15
  }>;
@@ -3,12 +3,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.createFfmpegComplexFilter = void 0;
4
4
  const create_ffmpeg_merge_filter_1 = require("./create-ffmpeg-merge-filter");
5
5
  const ffmpeg_filter_file_1 = require("./ffmpeg-filter-file");
6
- const createFfmpegComplexFilter = async (filters, downloadMap) => {
7
- if (filters === 0) {
6
+ const createFfmpegComplexFilter = async ({ filters, downloadMap, ffmpegExecutable, remotionRoot, }) => {
7
+ if (filters.length === 0) {
8
8
  return { complexFilterFlag: null, cleanup: () => undefined };
9
9
  }
10
- const complexFilter = (0, create_ffmpeg_merge_filter_1.createFfmpegMergeFilter)(filters);
11
- const { file, cleanup } = await (0, ffmpeg_filter_file_1.makeFfmpegFilterFile)(complexFilter, downloadMap);
10
+ const complexFilter = await (0, create_ffmpeg_merge_filter_1.createFfmpegMergeFilter)({
11
+ inputs: filters,
12
+ ffmpegExecutable,
13
+ remotionRoot,
14
+ });
15
+ const { file, cleanup } = await (0, ffmpeg_filter_file_1.makeFfmpegFilterFileStr)(complexFilter, downloadMap);
12
16
  return {
13
17
  complexFilterFlag: ['-filter_complex_script', file],
14
18
  cleanup,
@@ -1 +1,8 @@
1
- export declare const createFfmpegMergeFilter: (inputs: number) => string;
1
+ import type { FfmpegExecutable } from './ffmpeg-executable';
2
+ import type { PreprocessedAudioTrack } from './preprocess-audio-track';
3
+ export declare const OUTPUT_FILTER_NAME = "outputaudio";
4
+ export declare const createFfmpegMergeFilter: ({ inputs, ffmpegExecutable, remotionRoot, }: {
5
+ inputs: PreprocessedAudioTrack[];
6
+ ffmpegExecutable: FfmpegExecutable;
7
+ remotionRoot: string;
8
+ }) => Promise<string>;
@@ -1,7 +1,34 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createFfmpegMergeFilter = void 0;
4
- const createFfmpegMergeFilter = (inputs) => {
5
- return `[0:a][1:a]amix=inputs=${inputs}[a]`;
3
+ exports.createFfmpegMergeFilter = exports.OUTPUT_FILTER_NAME = void 0;
4
+ const ffmpeg_flags_1 = require("./ffmpeg-flags");
5
+ const truthy_1 = require("./truthy");
6
+ exports.OUTPUT_FILTER_NAME = 'outputaudio';
7
+ const createFfmpegMergeFilter = async ({ inputs, ffmpegExecutable, remotionRoot, }) => {
8
+ const ffmpegVersion = await (0, ffmpeg_flags_1.getFfmpegVersion)({
9
+ ffmpegExecutable,
10
+ remotionRoot,
11
+ });
12
+ const supportsNormalize = ffmpegVersion === null ||
13
+ (ffmpegVersion[0] === 4 && ffmpegVersion[1] >= 4) ||
14
+ ffmpegVersion[0] >= 5;
15
+ const pads = inputs.map((input, index) => {
16
+ const filters = [
17
+ input.filter.pad_start ? input.filter.pad_start : null,
18
+ input.filter.pad_end ? input.filter.pad_end : null,
19
+ 'acopy',
20
+ ];
21
+ return `[${index}:a]${filters.filter(truthy_1.truthy).join(',')}[padded${index}]`;
22
+ });
23
+ const normalize = supportsNormalize ? ':normalize=0' : '';
24
+ return [
25
+ ...pads,
26
+ `${new Array(inputs.length)
27
+ .fill(true)
28
+ .map((_, i) => {
29
+ return `[padded${i}]`;
30
+ })
31
+ .join('')}amix=inputs=${inputs.length}:dropout_transition=0${normalize}[${exports.OUTPUT_FILTER_NAME}]`,
32
+ ].join(';');
6
33
  };
7
34
  exports.createFfmpegMergeFilter = createFfmpegMergeFilter;
@@ -1 +1,4 @@
1
- export declare const determineResizeParams: (needsResize: [number, number] | null) => string[];
1
+ export declare const determineResizeParams: (needsResize: [
2
+ number,
3
+ number
4
+ ] | null) => string[];
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { OffthreadVideoImageFormat } from 'remotion';
3
2
  import type { DownloadMap } from './assets/download-map';
4
3
  import type { FfmpegExecutable } from './ffmpeg-executable';
@@ -1,5 +1,10 @@
1
1
  import type { DownloadMap } from './assets/download-map';
2
- export declare const makeFfmpegFilterFile: (complexFilter: string, downloadMap: DownloadMap) => Promise<{
2
+ import type { FilterWithoutPaddingApplied } from './stringify-ffmpeg-filter';
3
+ export declare const makeFfmpegFilterFile: (complexFilter: FilterWithoutPaddingApplied, downloadMap: DownloadMap) => Promise<{
4
+ file: string;
5
+ cleanup: () => void;
6
+ }>;
7
+ export declare const makeFfmpegFilterFileStr: (complexFilter: string, downloadMap: DownloadMap) => Promise<{
3
8
  file: string;
4
9
  cleanup: () => void;
5
10
  }>;
@@ -5,13 +5,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  return (mod && mod.__esModule) ? mod : { "default": mod };
6
6
  };
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.makeFfmpegFilterFile = void 0;
8
+ exports.makeFfmpegFilterFileStr = exports.makeFfmpegFilterFile = void 0;
9
9
  const fs_1 = __importDefault(require("fs"));
10
10
  const path_1 = __importDefault(require("path"));
11
11
  const makeFfmpegFilterFile = async (complexFilter, downloadMap) => {
12
12
  const random = Math.random().toString().replace('.', '');
13
13
  const filterFile = path_1.default.join(downloadMap.complexFilter, 'complex-filter-' + random + '.txt');
14
- await fs_1.default.promises.writeFile(filterFile, complexFilter);
14
+ await fs_1.default.promises.writeFile(filterFile, complexFilter.filter);
15
15
  return {
16
16
  file: filterFile,
17
17
  cleanup: () => {
@@ -20,3 +20,15 @@ const makeFfmpegFilterFile = async (complexFilter, downloadMap) => {
20
20
  };
21
21
  };
22
22
  exports.makeFfmpegFilterFile = makeFfmpegFilterFile;
23
+ const makeFfmpegFilterFileStr = async (complexFilter, downloadMap) => {
24
+ const random = Math.random().toString().replace('.', '');
25
+ const filterFile = path_1.default.join(downloadMap.complexFilter, 'complex-filter-' + random + '.txt');
26
+ await fs_1.default.promises.writeFile(filterFile, complexFilter);
27
+ return {
28
+ file: filterFile,
29
+ cleanup: () => {
30
+ fs_1.default.unlinkSync(filterFile);
31
+ },
32
+ };
33
+ };
34
+ exports.makeFfmpegFilterFileStr = makeFfmpegFilterFileStr;
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { OffthreadVideoImageFormat } from 'remotion';
3
2
  import type { SpecialVCodecForTransparency } from './assets/download-map';
4
3
  import type { FfmpegExecutable } from './ffmpeg-executable';
@@ -8,7 +7,10 @@ export declare const getFrameOfVideoSlow: ({ src, duration, ffmpegExecutable, im
8
7
  duration: number;
9
8
  imageFormat: OffthreadVideoImageFormat;
10
9
  specialVCodecForTransparency: SpecialVCodecForTransparency;
11
- needsResize: [number, number] | null;
10
+ needsResize: [
11
+ number,
12
+ number
13
+ ] | null;
12
14
  offset: number;
13
15
  fps: number | null;
14
16
  remotionRoot: string;
package/dist/index.d.ts CHANGED
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import execa from 'execa';
3
2
  import { SymbolicateableError } from './error-handling/symbolicateable-error';
4
3
  import { mimeContentType, mimeLookup } from './mime-types';
@@ -119,8 +118,8 @@ export declare const RenderInternals: {
119
118
  validPixelFormats: readonly ["yuv420p", "yuva420p", "yuv422p", "yuv444p", "yuv420p10le", "yuv422p10le", "yuv444p10le", "yuva444p10le"];
120
119
  DEFAULT_BROWSER: import("./browser").Browser;
121
120
  validateFrameRange: (frameRange: import("./frame-range").FrameRange | null) => void;
122
- DEFAULT_OPENGL_RENDERER: "swangle" | "angle" | "egl" | "swiftshader" | null;
123
- validateOpenGlRenderer: (option: "swangle" | "angle" | "egl" | "swiftshader" | null) => "swangle" | "angle" | "egl" | "swiftshader" | null;
121
+ DEFAULT_OPENGL_RENDERER: "angle" | "swangle" | "egl" | "swiftshader" | null;
122
+ validateOpenGlRenderer: (option: "angle" | "swangle" | "egl" | "swiftshader" | null) => "angle" | "swangle" | "egl" | "swiftshader" | null;
124
123
  validImageFormats: readonly ["png", "jpeg", "none"];
125
124
  validCodecs: readonly ["h264", "h265", "vp8", "vp9", "mp3", "aac", "wav", "prores", "h264-mkv", "gif"];
126
125
  DEFAULT_PIXEL_FORMAT: "yuv420p" | "yuva420p" | "yuv422p" | "yuv444p" | "yuv420p10le" | "yuv422p10le" | "yuv444p10le" | "yuva444p10le";
@@ -129,7 +128,7 @@ export declare const RenderInternals: {
129
128
  DEFAULT_CODEC: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif";
130
129
  isAudioCodec: (codec: "h264" | "h265" | "vp8" | "vp9" | "mp3" | "aac" | "wav" | "prores" | "h264-mkv" | "gif" | undefined) => boolean;
131
130
  logLevels: readonly ["verbose", "info", "warn", "error"];
132
- isEqualOrBelowLogLevel: (currentLevel: "verbose" | "error" | "info" | "warn", level: "verbose" | "error" | "info" | "warn") => boolean;
131
+ isEqualOrBelowLogLevel: (currentLevel: "error" | "verbose" | "info" | "warn", level: "error" | "verbose" | "info" | "warn") => boolean;
133
132
  isValidLogLevel: (level: string) => boolean;
134
133
  perf: typeof perf;
135
134
  makeDownloadMap: () => import("./assets/download-map").DownloadMap;
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { OffthreadVideoImageFormat } from 'remotion';
3
2
  import type { DownloadMap, SpecialVCodecForTransparency } from './assets/download-map';
4
3
  import type { FfmpegExecutable } from './ffmpeg-executable';
@@ -1,8 +1,9 @@
1
1
  import type { DownloadMap } from './assets/download-map';
2
2
  import type { FfmpegExecutable } from './ffmpeg-executable';
3
+ import type { PreprocessedAudioTrack } from './preprocess-audio-track';
3
4
  declare type Options = {
4
5
  ffmpegExecutable: FfmpegExecutable;
5
- files: string[];
6
+ files: PreprocessedAudioTrack[];
6
7
  outName: string;
7
8
  numberOfSeconds: number;
8
9
  downloadMap: DownloadMap;
@@ -5,10 +5,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.mergeAudioTrack = void 0;
7
7
  const execa_1 = __importDefault(require("execa"));
8
+ const fs_1 = require("fs");
8
9
  const path_1 = __importDefault(require("path"));
9
10
  const chunk_1 = require("./chunk");
10
- const convert_to_pcm_1 = require("./convert-to-pcm");
11
11
  const create_ffmpeg_complex_filter_1 = require("./create-ffmpeg-complex-filter");
12
+ const create_ffmpeg_merge_filter_1 = require("./create-ffmpeg-merge-filter");
12
13
  const create_silent_audio_1 = require("./create-silent-audio");
13
14
  const delete_directory_1 = require("./delete-directory");
14
15
  const ffmpeg_flags_1 = require("./ffmpeg-flags");
@@ -26,12 +27,7 @@ const mergeAudioTrackUnlimited = async ({ ffmpegExecutable, outName, files, numb
26
27
  return;
27
28
  }
28
29
  if (files.length === 1) {
29
- await (0, convert_to_pcm_1.convertToPcm)({
30
- outName,
31
- ffmpegExecutable,
32
- input: files[0],
33
- remotionRoot,
34
- });
30
+ (0, fs_1.copyFileSync)(files[0].outName, outName);
35
31
  return;
36
32
  }
37
33
  // In FFMPEG, the total number of left and right tracks that can be merged at one time is limited to 64
@@ -53,7 +49,13 @@ const mergeAudioTrackUnlimited = async ({ ffmpegExecutable, outName, files, numb
53
49
  }));
54
50
  await (0, exports.mergeAudioTrack)({
55
51
  ffmpegExecutable,
56
- files: chunkNames,
52
+ files: chunkNames.map((c) => ({
53
+ filter: {
54
+ pad_end: null,
55
+ pad_start: null,
56
+ },
57
+ outName: c,
58
+ })),
57
59
  numberOfSeconds,
58
60
  outName,
59
61
  downloadMap,
@@ -65,12 +67,17 @@ const mergeAudioTrackUnlimited = async ({ ffmpegExecutable, outName, files, numb
65
67
  (0, delete_directory_1.deleteDirectory)(tempPath);
66
68
  }
67
69
  }
68
- const { complexFilterFlag: mergeFilter, cleanup } = await (0, create_ffmpeg_complex_filter_1.createFfmpegComplexFilter)(files.length, downloadMap);
70
+ const { complexFilterFlag: mergeFilter, cleanup } = await (0, create_ffmpeg_complex_filter_1.createFfmpegComplexFilter)({
71
+ filters: files,
72
+ downloadMap,
73
+ ffmpegExecutable,
74
+ remotionRoot,
75
+ });
69
76
  const args = [
70
- ...files.map((f) => ['-i', f]),
77
+ ...files.map((f) => ['-i', f.outName]),
71
78
  mergeFilter,
72
79
  ['-c:a', 'pcm_s16le'],
73
- ['-map', '[a]'],
80
+ ['-map', `[${create_ffmpeg_merge_filter_1.OUTPUT_FILTER_NAME}]`],
74
81
  ['-y', outName],
75
82
  ]
76
83
  .filter(truthy_1.truthy)
@@ -1,6 +1,7 @@
1
1
  import type { DownloadMap } from './assets/download-map';
2
2
  import type { MediaAsset } from './assets/types';
3
3
  import type { FfmpegExecutable } from './ffmpeg-executable';
4
+ import type { ProcessedTrack } from './stringify-ffmpeg-filter';
4
5
  declare type Options = {
5
6
  ffmpegExecutable: FfmpegExecutable;
6
7
  ffprobeExecutable: FfmpegExecutable;
@@ -11,5 +12,9 @@ declare type Options = {
11
12
  downloadMap: DownloadMap;
12
13
  remotionRoot: string;
13
14
  };
14
- export declare const preprocessAudioTrack: (options: Options) => Promise<string | null>;
15
+ export declare type PreprocessedAudioTrack = {
16
+ outName: string;
17
+ filter: ProcessedTrack;
18
+ };
19
+ export declare const preprocessAudioTrack: (options: Options) => Promise<PreprocessedAudioTrack | null>;
15
20
  export {};
@@ -11,6 +11,7 @@ const ffmpeg_filter_file_1 = require("./ffmpeg-filter-file");
11
11
  const ffmpeg_flags_1 = require("./ffmpeg-flags");
12
12
  const p_limit_1 = require("./p-limit");
13
13
  const resolve_asset_src_1 = require("./resolve-asset-src");
14
+ const sample_rate_1 = require("./sample-rate");
14
15
  const preprocessAudioTrackUnlimited = async ({ ffmpegExecutable, ffprobeExecutable, outName, asset, expectedFrames, fps, downloadMap, remotionRoot, }) => {
15
16
  const { channels, duration } = await (0, get_audio_channels_1.getAudioChannelsAndDuration)(downloadMap, (0, resolve_asset_src_1.resolveAssetSrc)(asset.src), ffprobeExecutable, remotionRoot);
16
17
  const filter = (0, calculate_ffmpeg_filters_1.calculateFfmpegFilter)({
@@ -29,11 +30,12 @@ const preprocessAudioTrackUnlimited = async ({ ffmpegExecutable, ffprobeExecutab
29
30
  ['-ac', '2'],
30
31
  ['-filter_script:a', file],
31
32
  ['-c:a', 'pcm_s16le'],
33
+ ['-ar', String(sample_rate_1.DEFAULT_SAMPLE_RATE)],
32
34
  ['-y', outName],
33
35
  ].flat(2);
34
36
  await (0, execa_1.default)(await (0, ffmpeg_flags_1.getExecutableBinary)(ffmpegExecutable, remotionRoot, 'ffmpeg'), args);
35
37
  cleanup();
36
- return outName;
38
+ return { outName, filter };
37
39
  };
38
40
  const limit = (0, p_limit_1.pLimit)(2);
39
41
  const preprocessAudioTrack = (options) => {
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { ClipRegion } from 'remotion';
3
2
  import type { Page } from './browser/BrowserPage';
4
3
  import type { ImageFormat } from './image-format';
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { ClipRegion } from 'remotion';
3
2
  import type { Page } from './browser/BrowserPage';
4
3
  export declare const screenshot: (options: {
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { SmallTCompMetadata } from 'remotion';
3
2
  import type { RenderMediaOnDownload } from './assets/download-and-map-assets-to-file';
4
3
  import type { DownloadMap } from './assets/download-map';
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { ClipRegion } from 'remotion';
3
2
  import type { Page } from './browser/BrowserPage';
4
3
  import type { ImageFormat } from './image-format';
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { ClipRegion } from 'remotion';
3
2
  import type { Page } from './browser/BrowserPage';
4
3
  import type { StillImageFormat } from './image-format';
@@ -102,7 +102,7 @@ const getAssetsData = async ({ assets, onDownload, fps, expectedFrames, verbose,
102
102
  onProgress(1);
103
103
  (0, delete_directory_1.deleteDirectory)(downloadMap.audioMixing);
104
104
  preprocessed.forEach((p) => {
105
- (0, delete_directory_1.deleteDirectory)(p);
105
+ (0, delete_directory_1.deleteDirectory)(p.outName);
106
106
  });
107
107
  return outName;
108
108
  };
@@ -1,4 +1,11 @@
1
1
  import type { AssetVolume } from './assets/types';
2
+ export declare type FilterWithoutPaddingApplied = ProcessedTrack & {
3
+ filter: string;
4
+ };
5
+ export declare type ProcessedTrack = {
6
+ pad_start: string | null;
7
+ pad_end: string | null;
8
+ };
2
9
  export declare const stringifyFfmpegFilter: ({ trimLeft, trimRight, channels, startInVideo, volume, fps, playbackRate, durationInFrames, assetDuration, allowAmplificationDuringRender, }: {
3
10
  trimLeft: number;
4
11
  trimRight: number;
@@ -10,4 +17,4 @@ export declare const stringifyFfmpegFilter: ({ trimLeft, trimRight, channels, st
10
17
  playbackRate: number;
11
18
  assetDuration: number | null;
12
19
  allowAmplificationDuringRender: boolean;
13
- }) => string | null;
20
+ }) => FilterWithoutPaddingApplied | null;
@@ -23,37 +23,38 @@ const stringifyFfmpegFilter = ({ trimLeft, trimRight, channels, startInVideo, vo
23
23
  : trimRight;
24
24
  const audibleDuration = (actualTrimRight - trimLeft) / playbackRate;
25
25
  const padAtEnd = chunkLength - audibleDuration - startInVideoSeconds;
26
- return (`[0:a]` +
27
- [
28
- `aformat=sample_fmts=s32:sample_rates=${sample_rate_1.DEFAULT_SAMPLE_RATE}`,
29
- // Order matters! First trim the audio
30
- `atrim=${trimLeft.toFixed(6)}:${actualTrimRight.toFixed(6)}`,
31
- // then set the tempo
32
- (0, calculate_atempo_1.calculateATempo)(playbackRate),
33
- // set the volume if needed
34
- // The timings for volume must include whatever is in atrim, unless the volume
35
- // filter gets applied before atrim
36
- volumeFilter.value === '1'
37
- ? null
38
- : `volume=${volumeFilter.value}:eval=${volumeFilter.eval}`,
39
- // For n channels, we delay n + 1 channels.
40
- // This is because `ffprobe` for some audio files reports the wrong amount
41
- // of channels.
42
- // This should be fine because FFMPEG documentation states:
43
- // "Unused delays will be silently ignored."
44
- // https://ffmpeg.org/ffmpeg-filters.html#adelay
45
- startInVideoSeconds === 0
46
- ? null
47
- : `adelay=${new Array(channels + 1)
48
- .fill((startInVideoSeconds * 1000).toFixed(0))
49
- .join('|')}`,
50
- // Only in the end, we pad to the full length.
51
- padAtEnd > 0.0000001
52
- ? 'apad=pad_len=' + Math.round(padAtEnd * sample_rate_1.DEFAULT_SAMPLE_RATE)
53
- : null,
54
- ]
55
- .filter(truthy_1.truthy)
56
- .join(',') +
57
- `[a0]`);
26
+ return {
27
+ filter: `[0:a]` +
28
+ [
29
+ `aformat=sample_fmts=s32:sample_rates=${sample_rate_1.DEFAULT_SAMPLE_RATE}`,
30
+ // Order matters! First trim the audio
31
+ `atrim=${trimLeft.toFixed(6)}:${actualTrimRight.toFixed(6)}`,
32
+ // then set the tempo
33
+ (0, calculate_atempo_1.calculateATempo)(playbackRate),
34
+ // set the volume if needed
35
+ // The timings for volume must include whatever is in atrim, unless the volume
36
+ // filter gets applied before atrim
37
+ volumeFilter.value === '1'
38
+ ? null
39
+ : `volume=${volumeFilter.value}:eval=${volumeFilter.eval}`,
40
+ // For n channels, we delay n + 1 channels.
41
+ // This is because `ffprobe` for some audio files reports the wrong amount
42
+ // of channels.
43
+ // This should be fine because FFMPEG documentation states:
44
+ // "Unused delays will be silently ignored."
45
+ // https://ffmpeg.org/ffmpeg-filters.html#adelay
46
+ ]
47
+ .filter(truthy_1.truthy)
48
+ .join(',') +
49
+ `[a0]`,
50
+ pad_end: padAtEnd > 0.0000001
51
+ ? 'apad=pad_len=' + Math.round(padAtEnd * sample_rate_1.DEFAULT_SAMPLE_RATE)
52
+ : null,
53
+ pad_start: startInVideoSeconds === 0
54
+ ? null
55
+ : `adelay=${new Array(channels + 1)
56
+ .fill((startInVideoSeconds * 1000).toFixed(0))
57
+ .join('|')}`,
58
+ };
58
59
  };
59
60
  exports.stringifyFfmpegFilter = stringifyFfmpegFilter;
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { TAsset } from 'remotion';
3
2
  import type { DownloadMap } from './assets/download-map';
4
3
  import type { Page } from './browser/BrowserPage';
@@ -1,4 +1,3 @@
1
- /// <reference types="node" />
2
1
  import type { OffthreadVideoImageFormat } from 'remotion';
3
2
  import type { NeedsResize, SpecialVCodecForTransparency } from './assets/download-map';
4
3
  import type { FfmpegExecutable } from './ffmpeg-executable';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/renderer",
3
- "version": "3.3.61",
3
+ "version": "3.3.62",
4
4
  "description": "Renderer for Remotion",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -24,7 +24,7 @@
24
24
  "dependencies": {
25
25
  "execa": "5.1.1",
26
26
  "extract-zip": "2.0.1",
27
- "remotion": "3.3.61",
27
+ "remotion": "3.3.62",
28
28
  "source-map": "^0.8.0-beta.0",
29
29
  "ws": "8.7.0"
30
30
  },
@@ -49,13 +49,13 @@
49
49
  "vitest": "0.24.3"
50
50
  },
51
51
  "optionalDependencies": {
52
- "@remotion/compositor-darwin-arm64": "3.3.61",
53
- "@remotion/compositor-darwin-x64": "3.3.61",
54
- "@remotion/compositor-linux-arm64-gnu": "3.3.61",
55
- "@remotion/compositor-linux-arm64-musl": "3.3.61",
56
- "@remotion/compositor-linux-x64-gnu": "3.3.61",
57
- "@remotion/compositor-linux-x64-musl": "3.3.61",
58
- "@remotion/compositor-win32-x64-msvc": "3.3.61"
52
+ "@remotion/compositor-darwin-arm64": "3.3.62",
53
+ "@remotion/compositor-darwin-x64": "3.3.62",
54
+ "@remotion/compositor-linux-arm64-gnu": "3.3.62",
55
+ "@remotion/compositor-linux-arm64-musl": "3.3.62",
56
+ "@remotion/compositor-linux-x64-gnu": "3.3.62",
57
+ "@remotion/compositor-linux-x64-musl": "3.3.62",
58
+ "@remotion/compositor-win32-x64-msvc": "3.3.62"
59
59
  },
60
60
  "keywords": [
61
61
  "remotion",
@@ -67,5 +67,5 @@
67
67
  "publishConfig": {
68
68
  "access": "public"
69
69
  },
70
- "gitHead": "c2d7a7088e4a9939c95168e03d7e29e3f6d63973"
70
+ "gitHead": "8fb0700ad70d5feca5fa86c414434757d323292a"
71
71
  }