@marcuth/movie.js 0.1.3 โ†’ 0.2.0

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.
package/README.md ADDED
@@ -0,0 +1,164 @@
1
+ # Movie.js
2
+
3
+ **Movie.js** is a library built on top of `fluent-ffmpeg` designed to create templates for generating standardized videos with dataโ€”which can be static or dynamic. It simplifies the process of sequencing video, image, and audio clips into a final composition.
4
+
5
+ ## ๐Ÿ“ฆ Installation
6
+
7
+ Installation is straightforward; just use your preferred package manager. Here is an example using NPM:
8
+
9
+ ```bash
10
+ npm i @marcuth/movie.js
11
+ ```
12
+
13
+ > **Note:** You must have FFMPEG installed on your system for this library to work.
14
+
15
+ ## ๐Ÿš€ Usage
16
+
17
+ <a href="https://www.buymeacoffee.com/marcuth">
18
+ <img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="200">
19
+ </a>
20
+
21
+ ### Template
22
+
23
+ The foundation for creating videos in Movie.js is the `Template`. This is where you define your clips and configuration.
24
+
25
+ ```ts
26
+ import movie from "@marcuth/movie.js"
27
+
28
+ type RenderData = {
29
+ heroImage: string
30
+ backgroundVideo: string
31
+ }
32
+
33
+ const template = movie.template<RenderData>({
34
+ config: {
35
+ format: "mp4",
36
+ fps: 30,
37
+ outputOptions: ["-preset ultrafast"] // optional ffmpeg output options
38
+ },
39
+ clips: [
40
+ // ... your clips here
41
+ ]
42
+ })
43
+
44
+ // Render the template with data
45
+ const result = await template.render({
46
+ heroImage: "/path/to/image.png",
47
+ backgroundVideo: "/path/to/video.mp4"
48
+ })
49
+
50
+ // Save the result
51
+ result.save("output.mp4")
52
+ ```
53
+
54
+ ---
55
+
56
+ ### Clips
57
+
58
+ Clips are the building blocks of your video. They represent individual media segments like videos, images, or audio tracks.
59
+
60
+ Most file paths in clips support dynamic resolution:
61
+ ```ts
62
+ path: ({ data, index }) => data.myPath
63
+ ```
64
+
65
+ #### VideoClip
66
+
67
+ To insert a video segment:
68
+
69
+ ```ts
70
+ movie.video({
71
+ path: "assets/intro.mp4",
72
+ fadeIn: 1, // seconds
73
+ fadeOut: 1, // seconds
74
+ subClip: [0, 5] // [start, duration] - Clip from 0s to 5s
75
+ })
76
+ ```
77
+
78
+ #### ImageClip
79
+
80
+ To insert an image with optional scrolling/Ken Burns effect:
81
+
82
+ ```ts
83
+ movie.image({
84
+ path: ({ data }) => data.heroImage,
85
+ duration: 5, // seconds
86
+ width: 1920, // force resize width
87
+ height: 1080, // force resize height
88
+ scroll: {
89
+ axis: "y", // "x", "y", or "auto"
90
+ direction: "forward",
91
+ easing: "easeInOut"
92
+ },
93
+ fadeIn: 0.5
94
+ })
95
+ ```
96
+
97
+ #### AudioClip
98
+
99
+ To add audio (background music, sound effects):
100
+
101
+ ```ts
102
+ movie.audio({
103
+ path: "assets/music.mp3",
104
+ volume: 0.5,
105
+ fadeIn: 2,
106
+ fadeOut: 2
107
+ })
108
+ ```
109
+
110
+ ---
111
+
112
+ ### Structural Clips
113
+
114
+ #### RepeatClip
115
+
116
+ If you need to loop over an array of data to generate clips:
117
+
118
+ ```ts
119
+ movie.repeat({
120
+ each: ({ data }) => data.items, // Array of items
121
+ clip: (item, index) => movie.video({
122
+ path: item.videoPath
123
+ })
124
+ })
125
+ ```
126
+
127
+ #### CompositionClip
128
+
129
+ Group multiple clips together. Useful for organizing sequences:
130
+
131
+ ```ts
132
+ movie.composition({
133
+ clips: [
134
+ movie.video({ ... }),
135
+ movie.video({ ... })
136
+ ]
137
+ })
138
+ ```
139
+
140
+ #### ConcatenationClip
141
+
142
+ Explicitly concatenate a list of clips:
143
+
144
+ ```ts
145
+ movie.concatenation({
146
+ clips: [ ... ]
147
+ })
148
+ ```
149
+
150
+ ---
151
+
152
+ ## ๐Ÿค Contributing
153
+
154
+ Want to contribute? Follow these steps:
155
+
156
+ 1. Fork the repository.
157
+ 2. Create a new branch (`git checkout -b feature-new`).
158
+ 3. Commit your changes (`git commit -m 'Add new feature'`).
159
+ 4. Push to the branch (`git push origin feature-new`).
160
+ 5. Open a Pull Request.
161
+
162
+ ## ๐Ÿ“ License
163
+
164
+ This project is licensed under the MIT License.
@@ -6,12 +6,14 @@ export type VideoClipOptions<RenderData> = {
6
6
  path: Path<RenderData>;
7
7
  fadeIn?: number;
8
8
  fadeOut?: number;
9
+ subClip?: [number, number];
9
10
  };
10
11
  export declare class VideoClip<RenderData> extends Clip<RenderData> {
11
12
  readonly path: Path<RenderData>;
12
13
  readonly fadeIn?: number;
13
14
  readonly fadeOut?: number;
14
- constructor({ path, fadeIn, fadeOut }: VideoClipOptions<RenderData>);
15
+ readonly subClip?: [number, number];
16
+ constructor({ path, fadeIn, fadeOut, subClip }: VideoClipOptions<RenderData>);
15
17
  protected getInput(path: string, inputIndex: number): FFmpegInput;
16
18
  getDuration(path: string): Promise<number>;
17
19
  build(data: RenderData, context: RenderContext): Promise<void>;
@@ -5,11 +5,12 @@ const fluent_ffmpeg_1 = require("fluent-ffmpeg");
5
5
  const resolve_path_1 = require("../utils/resolve-path");
6
6
  const clip_1 = require("./clip");
7
7
  class VideoClip extends clip_1.Clip {
8
- constructor({ path, fadeIn, fadeOut }) {
8
+ constructor({ path, fadeIn, fadeOut, subClip }) {
9
9
  super();
10
10
  this.path = path;
11
11
  this.fadeIn = fadeIn;
12
12
  this.fadeOut = fadeOut;
13
+ this.subClip = subClip;
13
14
  }
14
15
  getInput(path, inputIndex) {
15
16
  return {
@@ -37,8 +38,13 @@ class VideoClip extends clip_1.Clip {
37
38
  const input = this.getInput(path, context.inputIndex);
38
39
  let currentVideoOutput = input.aliases.video;
39
40
  let currentAudioOutput = input.aliases.audio;
40
- const duration = await this.getDuration(path);
41
+ let duration = await this.getDuration(path);
41
42
  context.command.input(path);
43
+ if (this.subClip) {
44
+ const [start, subDuration] = this.subClip;
45
+ context.command.inputOptions([`-ss ${start}`, `-t ${subDuration}`]);
46
+ duration = subDuration;
47
+ }
42
48
  if (this.fadeIn !== undefined && this.fadeIn > 0) {
43
49
  const fadeInOutput = `[fadeIn${context.inputIndex}]`;
44
50
  const fadeInAudioOutput = `[fadeInAudio${context.inputIndex}]`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@marcuth/movie.js",
3
- "version": "0.1.3",
3
+ "version": "0.2.0",
4
4
  "description": "Video template builder",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",