screenkit 0.0.1 → 0.0.3
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.
- checksums.yaml +4 -4
- data/.github/workflows/docker.yml +46 -0
- data/.github/workflows/ruby-tests.yml +21 -1
- data/Brewfile +5 -0
- data/CHANGELOG.md +11 -0
- data/CONTRIBUTING.md +25 -0
- data/DOCUMENTATION.md +136 -41
- data/Dockerfile +107 -0
- data/lib/screen_kit.rb +15 -16
- data/lib/screenkit/animation_filters.rb +16 -0
- data/lib/screenkit/callout/styles/base.rb +12 -0
- data/lib/screenkit/callout/styles/file_copy.rb +26 -0
- data/lib/screenkit/callout/styles/inline_block.rb +6 -9
- data/lib/screenkit/callout/styles/{default.rb → shadow_block.rb} +9 -11
- data/lib/screenkit/callout.rb +1 -1
- data/lib/screenkit/cli/episode.rb +2 -3
- data/lib/screenkit/cli/root.rb +1 -1
- data/lib/screenkit/config/episode.rb +6 -0
- data/lib/screenkit/config/project.rb +5 -2
- data/lib/screenkit/exporter/demotape.rb +8 -0
- data/lib/screenkit/exporter/episode.rb +37 -17
- data/lib/screenkit/exporter/segment.rb +262 -71
- data/lib/screenkit/generators/episode/callouts/001.yml +12 -0
- data/lib/screenkit/generators/episode/config.yml.erb +8 -8
- data/lib/screenkit/generators/project/screenkit.yml +46 -15
- data/lib/screenkit/schema_validator.rb +1 -1
- data/lib/screenkit/schemas/callout_styles/file_copy.json +8 -0
- data/lib/screenkit/schemas/callout_styles/inline_block.json +20 -0
- data/lib/screenkit/schemas/{callouts/default.json → callout_styles/shadow_block.json} +2 -2
- data/lib/screenkit/schemas/callouts/inline_block.json +20 -11
- data/lib/screenkit/schemas/callouts/shadow_block.json +39 -0
- data/lib/screenkit/schemas/episode.json +6 -43
- data/lib/screenkit/schemas/project.json +4 -5
- data/lib/screenkit/schemas/refs/anchor.json +1 -1
- data/lib/screenkit/schemas/refs/animation.json +1 -1
- data/lib/screenkit/schemas/refs/background.json +1 -1
- data/lib/screenkit/schemas/refs/{callout.json → callout_style.json} +6 -8
- data/lib/screenkit/schemas/refs/color.json +1 -1
- data/lib/screenkit/schemas/refs/demotape.json +1 -1
- data/lib/screenkit/schemas/refs/demotape_themes.json +1 -1
- data/lib/screenkit/schemas/refs/directory.json +1 -1
- data/lib/screenkit/schemas/refs/duration.json +1 -1
- data/lib/screenkit/schemas/refs/intro.json +1 -1
- data/lib/screenkit/schemas/refs/logo.json +1 -1
- data/lib/screenkit/schemas/refs/outro.json +1 -1
- data/lib/screenkit/schemas/refs/position.json +1 -1
- data/lib/screenkit/schemas/refs/scenes.json +1 -1
- data/lib/screenkit/schemas/refs/size.json +1 -1
- data/lib/screenkit/schemas/refs/sound.json +1 -1
- data/lib/screenkit/schemas/refs/spacing.json +1 -1
- data/lib/screenkit/schemas/refs/text_style.json +1 -1
- data/lib/screenkit/schemas/refs/transition.json +1 -1
- data/lib/screenkit/schemas/refs/tts.json +4 -41
- data/lib/screenkit/schemas/refs/tts_builtin.json +23 -0
- data/lib/screenkit/schemas/refs/watermark.json +1 -1
- data/lib/screenkit/schemas/tts/elevenlabs.json +11 -2
- data/lib/screenkit/schemas/tts/espeak.json +26 -0
- data/lib/screenkit/schemas/tts/say.json +11 -1
- data/lib/screenkit/shell.rb +6 -0
- data/lib/screenkit/time_formatter.rb +14 -0
- data/lib/screenkit/tts/base.rb +21 -0
- data/lib/screenkit/tts/eleven_labs.rb +8 -9
- data/lib/screenkit/tts/espeak.rb +30 -0
- data/lib/screenkit/tts/say.rb +5 -6
- data/lib/screenkit/utils.rb +6 -0
- data/lib/screenkit/version.rb +1 -1
- metadata +21 -42
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-Bold.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-BoldItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-ExtraBoldItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-Italic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-Light.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-LightItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-Medium.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-MediumItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-Regular.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans-SemiBoldItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-Bold.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-BoldItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-ExtraBold.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-Italic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-Light.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-LightItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-Medium.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-MediumItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-Regular.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-SemiBold.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-Bold.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-Italic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-Light.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-Medium.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-Regular.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
- data/lib/screenkit/generators/project/resources/fonts/open-sans/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6cf85172336bdd8b19097835329c4deef29f9d2b57ab5b3caa1f1f2cb5681226
|
|
4
|
+
data.tar.gz: 69ba53b85b77fea9292a1833a3195467a3e782481a67b94b75983c47d89afb24
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d98ebece57b893b59766b61ba359f0ef44038e17f08d812eaa870f94f502662a23a18e6582674fd494630b492b3cf5d44f256735ddf690ed5604cf775fcd1f2
|
|
7
|
+
data.tar.gz: be1ad9cddd204eb4ecff40f9eb2d1c2490f713770cb7d3957e7fe870b9bad14838d2fa4abca53f9ebc6207d07fbdd9773d53e4a76d48bea82a9343635754faf9
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docker-image
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
paths:
|
|
8
|
+
- Dockerfile
|
|
9
|
+
tags:
|
|
10
|
+
- v*
|
|
11
|
+
workflow_dispatch:
|
|
12
|
+
inputs:
|
|
13
|
+
ref:
|
|
14
|
+
description: "Git ref to build the image from"
|
|
15
|
+
required: false
|
|
16
|
+
default: "main"
|
|
17
|
+
|
|
18
|
+
concurrency:
|
|
19
|
+
group: image-workflow
|
|
20
|
+
cancel-in-progress: true
|
|
21
|
+
|
|
22
|
+
jobs:
|
|
23
|
+
build:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v4
|
|
27
|
+
with:
|
|
28
|
+
ref: ${{ github.event.inputs.ref }}
|
|
29
|
+
|
|
30
|
+
- run: >
|
|
31
|
+
echo "IMAGE_TAG=${{ (inputs.ref || github.ref_name) == 'main' &&
|
|
32
|
+
'latest' || (inputs.ref || github.ref_name) }}" >> $GITHUB_ENV
|
|
33
|
+
|
|
34
|
+
- name: Build Docker Image
|
|
35
|
+
run: |
|
|
36
|
+
docker build -t fnando/screenkit:${{ env.IMAGE_TAG }} .
|
|
37
|
+
|
|
38
|
+
- name: Login to Docker Hub
|
|
39
|
+
uses: docker/login-action@v3
|
|
40
|
+
with:
|
|
41
|
+
username: ${{ secrets.DOCKER_HUB_USERNAME }}
|
|
42
|
+
password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
|
|
43
|
+
|
|
44
|
+
- name: Push Docker Image
|
|
45
|
+
run: |
|
|
46
|
+
docker push fnando/screenkit:${{ env.IMAGE_TAG }}
|
|
@@ -24,7 +24,7 @@ jobs:
|
|
|
24
24
|
- Gemfile
|
|
25
25
|
|
|
26
26
|
steps:
|
|
27
|
-
- uses: actions/checkout@
|
|
27
|
+
- uses: actions/checkout@v6
|
|
28
28
|
|
|
29
29
|
- uses: actions/cache@v4
|
|
30
30
|
with:
|
|
@@ -36,6 +36,26 @@ jobs:
|
|
|
36
36
|
with:
|
|
37
37
|
ruby-version: ${{ matrix.ruby }}
|
|
38
38
|
|
|
39
|
+
- name: Install system dependencies
|
|
40
|
+
run: |
|
|
41
|
+
# Install ImageMagick and zsh
|
|
42
|
+
sudo apt-get update
|
|
43
|
+
sudo apt-get install -y imagemagick zsh espeak
|
|
44
|
+
|
|
45
|
+
# Download and install FFmpeg 8
|
|
46
|
+
wget --quiet https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl.tar.xz
|
|
47
|
+
tar -xf ffmpeg-master-latest-linux64-gpl.tar.xz
|
|
48
|
+
sudo cp ffmpeg-master-latest-linux64-gpl/bin/ffmpeg /usr/local/bin/
|
|
49
|
+
sudo cp ffmpeg-master-latest-linux64-gpl/bin/ffprobe /usr/local/bin/
|
|
50
|
+
|
|
51
|
+
# Download and install ttyd
|
|
52
|
+
wget --quiet https://github.com/tsl0922/ttyd/releases/download/1.7.7/ttyd.x86_64
|
|
53
|
+
chmod +x ttyd.x86_64
|
|
54
|
+
sudo mv ttyd.x86_64 /usr/local/bin/ttyd
|
|
55
|
+
|
|
56
|
+
# Install ffmpeg-normalize
|
|
57
|
+
pip3 install ffmpeg-normalize
|
|
58
|
+
|
|
39
59
|
- name: Install gem dependencies
|
|
40
60
|
env:
|
|
41
61
|
BUNDLE_GEMFILE: ${{ matrix.gemfile }}
|
data/Brewfile
ADDED
data/CHANGELOG.md
CHANGED
|
@@ -11,6 +11,17 @@ Prefix your message with one of the following:
|
|
|
11
11
|
- [Security] in case of vulnerabilities.
|
|
12
12
|
-->
|
|
13
13
|
|
|
14
|
+
## v0.0.3
|
|
15
|
+
|
|
16
|
+
- [Changed] Do not expand path when creating project/episode.
|
|
17
|
+
|
|
18
|
+
## v0.0.2
|
|
19
|
+
|
|
20
|
+
- [Added] Add file copy callout style, to copy files to the final output path.
|
|
21
|
+
- [Changed] Copy only two OpenSans font files.
|
|
22
|
+
- [Changed] Rename the default callout to `shadow_block`.
|
|
23
|
+
- [Fixed] Changed all JSON Schema files to use a consistent url.
|
|
24
|
+
|
|
14
25
|
## v0.0.1
|
|
15
26
|
|
|
16
27
|
- [Added] Allow configuring Demo Tape using episode or project configuration.
|
data/CONTRIBUTING.md
CHANGED
|
@@ -32,6 +32,31 @@ by [opening an issue on Github](https://github.com/fnando/screenkit/issues).
|
|
|
32
32
|
When you're ready to make your pull request, follow checklist below to make sure
|
|
33
33
|
your contribution is according to how this project works.
|
|
34
34
|
|
|
35
|
+
### Setting up your environment
|
|
36
|
+
|
|
37
|
+
This project requires the following dependencies:
|
|
38
|
+
|
|
39
|
+
- ffmpeg
|
|
40
|
+
- imagemagick
|
|
41
|
+
- espeak
|
|
42
|
+
- ruby
|
|
43
|
+
- ffmpeg-normalize
|
|
44
|
+
|
|
45
|
+
If you are using macOS, you can install them using [Homebrew](https://brew.sh).
|
|
46
|
+
There's a Brewfile at the root directory with the required dependencies:
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
brew bundle install
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
For ffmpeg-normalize, you can use pip:
|
|
53
|
+
|
|
54
|
+
```sh
|
|
55
|
+
pip install ffmpeg-normalize --user
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
### Guidelines
|
|
59
|
+
|
|
35
60
|
1. [Fork](https://help.github.com/forking/) screenkit
|
|
36
61
|
2. Create a topic branch - `git checkout -b my_branch`
|
|
37
62
|
3. Make your changes using [descriptive commit messages](#commit-messages)
|
data/DOCUMENTATION.md
CHANGED
|
@@ -36,6 +36,17 @@ Or add to your Gemfile:
|
|
|
36
36
|
gem "screenkit"
|
|
37
37
|
```
|
|
38
38
|
|
|
39
|
+
### Docker
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
docker run --shm-size=2g -v $PWD:/source --rm -it docker.io/fnando/screenkit
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Notice that Chrome requires a lot of memory, so you need `--shm-size=2g` (or
|
|
46
|
+
more).
|
|
47
|
+
|
|
48
|
+
To create a new project:
|
|
49
|
+
|
|
39
50
|
---
|
|
40
51
|
|
|
41
52
|
## Quick Start
|
|
@@ -215,7 +226,7 @@ Define reusable callout styles:
|
|
|
215
226
|
|
|
216
227
|
```yaml
|
|
217
228
|
callouts:
|
|
218
|
-
|
|
229
|
+
shadow_block:
|
|
219
230
|
background_color: "#ffff00"
|
|
220
231
|
shadow: "#2242d3" # Color string or false
|
|
221
232
|
|
|
@@ -311,7 +322,6 @@ callouts:
|
|
|
311
322
|
|
|
312
323
|
- **Seconds**: `starts_at: 90` (90 seconds)
|
|
313
324
|
- **HH:MM:SS**: `starts_at: "00:01:30"` (1 minute 30 seconds)
|
|
314
|
-
- **Duration**: Always in seconds or time units (`5s`, `2m`, `1h`)
|
|
315
325
|
|
|
316
326
|
---
|
|
317
327
|
|
|
@@ -397,14 +407,15 @@ during the video.
|
|
|
397
407
|
|
|
398
408
|
ScreenKit provides two built-in callout styles:
|
|
399
409
|
|
|
400
|
-
####
|
|
410
|
+
#### Shadow Block Style
|
|
401
411
|
|
|
402
|
-
The
|
|
412
|
+
The shadow block style displays a title and body in a box with optional shadow.
|
|
403
413
|
|
|
404
414
|
```yaml
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
style:
|
|
415
|
+
callout_styles:
|
|
416
|
+
shadow_block: # This key can be anything.
|
|
417
|
+
style: shadow_block # The callout style name (will resolve to
|
|
418
|
+
# a ruby class).
|
|
408
419
|
background_color: "#ffff00" # Background color (hex)
|
|
409
420
|
|
|
410
421
|
# Shadow
|
|
@@ -445,11 +456,11 @@ callouts:
|
|
|
445
456
|
volume: 0.7 # Volume (0.0 to 1.0)
|
|
446
457
|
```
|
|
447
458
|
|
|
448
|
-
|
|
459
|
+
##### Usage in episode
|
|
449
460
|
|
|
450
461
|
```yaml
|
|
451
462
|
callouts:
|
|
452
|
-
- type:
|
|
463
|
+
- type: shadow_block
|
|
453
464
|
title: "ScreenKit"
|
|
454
465
|
body: "Visit https://github.com/fnando/screenkit"
|
|
455
466
|
starts_at: 3
|
|
@@ -463,27 +474,24 @@ similar to syntax highlighting or code comments. Perfect for displaying code
|
|
|
463
474
|
snippets, commands, or short inline text.
|
|
464
475
|
|
|
465
476
|
```yaml
|
|
466
|
-
|
|
467
|
-
code:
|
|
468
|
-
style: inline_block
|
|
477
|
+
callouts_styles:
|
|
478
|
+
code: # This key can be anything.
|
|
479
|
+
style: inline_block # Will resolve to a ruby class.
|
|
469
480
|
background_color: "#000000" # Background color (hex)
|
|
470
481
|
|
|
471
|
-
# Text Style (single style for all text)
|
|
472
482
|
text_style:
|
|
473
483
|
color: "#ffffff"
|
|
474
484
|
size: 40
|
|
475
485
|
font_path: open-sans/OpenSans-ExtraBold.ttf
|
|
476
486
|
|
|
477
487
|
# Layout
|
|
478
|
-
padding: 20
|
|
479
|
-
margin: 100
|
|
480
|
-
anchor: [left, center]
|
|
481
|
-
width: 600
|
|
488
|
+
padding: 20
|
|
489
|
+
margin: 100
|
|
490
|
+
anchor: [left, center]
|
|
491
|
+
width: 600
|
|
482
492
|
|
|
483
|
-
|
|
484
|
-
animation: fade # "fade" or "slide"
|
|
493
|
+
animation: fade
|
|
485
494
|
|
|
486
|
-
# Transitions
|
|
487
495
|
in_transition:
|
|
488
496
|
duration: 0.4
|
|
489
497
|
sound: false
|
|
@@ -493,7 +501,7 @@ callouts:
|
|
|
493
501
|
sound: false
|
|
494
502
|
```
|
|
495
503
|
|
|
496
|
-
|
|
504
|
+
##### Usage in episode
|
|
497
505
|
|
|
498
506
|
```yaml
|
|
499
507
|
callouts:
|
|
@@ -513,14 +521,91 @@ callouts:
|
|
|
513
521
|
duration: 6
|
|
514
522
|
```
|
|
515
523
|
|
|
516
|
-
|
|
524
|
+
#### File Copy Style
|
|
525
|
+
|
|
526
|
+
This is not a callout style per se. Instead, you can copy a file to the final
|
|
527
|
+
output directory during episode export. Useful for adding custom assets that may
|
|
528
|
+
be produced outside of ScreenKit.
|
|
517
529
|
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
530
|
+
```yaml
|
|
531
|
+
callouts_styles:
|
|
532
|
+
file_copy: # This key can be anything.
|
|
533
|
+
style: file_copy
|
|
534
|
+
|
|
535
|
+
# Layout
|
|
536
|
+
padding: 20
|
|
537
|
+
margin: 100
|
|
538
|
+
anchor: [left, center]
|
|
539
|
+
width: 600
|
|
540
|
+
|
|
541
|
+
animation: fade
|
|
542
|
+
|
|
543
|
+
in_transition:
|
|
544
|
+
duration: 0.4
|
|
545
|
+
sound: false
|
|
546
|
+
|
|
547
|
+
out_transition:
|
|
548
|
+
duration: 0.3
|
|
549
|
+
sound: false
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
##### Usage in episode
|
|
553
|
+
|
|
554
|
+
```yaml
|
|
555
|
+
callouts:
|
|
556
|
+
- type: file_copy
|
|
557
|
+
file_path: images/social_card.png
|
|
558
|
+
```
|
|
559
|
+
|
|
560
|
+
```yaml
|
|
561
|
+
callouts:
|
|
562
|
+
- type: file_copy
|
|
563
|
+
file_path: videos/social_card.mov
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
> [!NOTE]
|
|
567
|
+
>
|
|
568
|
+
> When copying a video file, the video will be used as an overlay, without
|
|
569
|
+
> resizing or repositioning. That means your overlay needs to be exactly
|
|
570
|
+
> 1920x1080 and 24 FPS. If the video has sound, it will be kept on the final
|
|
571
|
+
> output.
|
|
572
|
+
|
|
573
|
+
#### Custom Callout Styles
|
|
574
|
+
|
|
575
|
+
You can create custom callout styles by placing them in the
|
|
576
|
+
`ScreenKit::Callout::Styles` namespace.
|
|
577
|
+
|
|
578
|
+
```ruby
|
|
579
|
+
module ScreenKit
|
|
580
|
+
class Callout
|
|
581
|
+
module Styles
|
|
582
|
+
class SomeStyle < Base
|
|
583
|
+
extend SchemaValidator
|
|
584
|
+
|
|
585
|
+
def self.schema_path
|
|
586
|
+
"some/path/to/your/schema.json"
|
|
587
|
+
end
|
|
588
|
+
|
|
589
|
+
# `source` is the way you search for resources.
|
|
590
|
+
# `output_path` is where you must save the generated callout file.
|
|
591
|
+
# `log_path` is where you can write logs (optional).
|
|
592
|
+
def initialize(source:, output_path:, log_path:, **options)
|
|
593
|
+
self.class.validate!(options)
|
|
594
|
+
|
|
595
|
+
@source = source
|
|
596
|
+
@output_path = output_path
|
|
597
|
+
@log_path = log_path
|
|
598
|
+
@options = options
|
|
599
|
+
end
|
|
600
|
+
|
|
601
|
+
def render
|
|
602
|
+
# Generate the image/video that will be used as a callout.
|
|
603
|
+
end
|
|
604
|
+
end
|
|
605
|
+
end
|
|
606
|
+
end
|
|
607
|
+
end
|
|
608
|
+
```
|
|
524
609
|
|
|
525
610
|
### Anchor Positions
|
|
526
611
|
|
|
@@ -607,28 +692,33 @@ module. Custom engines must implement the `generate` method:
|
|
|
607
692
|
```ruby
|
|
608
693
|
module ScreenKit
|
|
609
694
|
module TTS
|
|
610
|
-
class CustomEngine
|
|
695
|
+
class CustomEngine < Base
|
|
611
696
|
include Shell
|
|
612
|
-
extend SchemaValidator
|
|
613
697
|
|
|
614
698
|
# Optional: Define schema path for validation
|
|
615
699
|
def self.schema_path
|
|
616
700
|
ScreenKit.root_dir.join("screenkit/schemas/tts/custom_engine.json")
|
|
617
701
|
end
|
|
618
702
|
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
self.class.validate!(@options) if respond_to?(:validate!)
|
|
703
|
+
# This method is required.
|
|
704
|
+
def available?
|
|
705
|
+
enabled? && command_exist?("some-command")
|
|
623
706
|
end
|
|
624
707
|
|
|
708
|
+
# This method is required.
|
|
625
709
|
def generate(text:, output_path:, log_path: nil)
|
|
710
|
+
# Optional: validate options against JSON schema.
|
|
711
|
+
self.class.validate!(options)
|
|
712
|
+
|
|
626
713
|
# Generate audio file from text
|
|
627
714
|
# Write output to output_path
|
|
628
715
|
# Optionally log to log_path
|
|
629
716
|
|
|
630
717
|
# Example implementation:
|
|
631
|
-
#
|
|
718
|
+
# run_command "some-command",
|
|
719
|
+
# "-o", output_path.sub_ext(".wav"),
|
|
720
|
+
# text,
|
|
721
|
+
# log_path:
|
|
632
722
|
end
|
|
633
723
|
end
|
|
634
724
|
end
|
|
@@ -700,8 +790,12 @@ out_transition:
|
|
|
700
790
|
```
|
|
701
791
|
episodes/001-episode-name/
|
|
702
792
|
├── config.yml # Episode configuration
|
|
793
|
+
├── callouts/ # Callout definitions
|
|
794
|
+
│ ├── 001.yml # Callouts that will appear on segment 001
|
|
795
|
+
│ ├── 002.yml
|
|
796
|
+
│ └── ...
|
|
703
797
|
├── content/ # Terminal recordings
|
|
704
|
-
│ ├── 001.tape
|
|
798
|
+
│ ├── 001.tape # Demo Tape files
|
|
705
799
|
│ ├── 002.tape
|
|
706
800
|
│ └── ...
|
|
707
801
|
├── scripts/ # Voiceover scripts
|
|
@@ -718,9 +812,9 @@ episodes/001-episode-name/
|
|
|
718
812
|
└── fonts/
|
|
719
813
|
```
|
|
720
814
|
|
|
721
|
-
###
|
|
815
|
+
### Demo Tape Files
|
|
722
816
|
|
|
723
|
-
ScreenKit uses [
|
|
817
|
+
ScreenKit uses [Demo Tape](https://github.com/fnando/demotape) tape files for
|
|
724
818
|
terminal recordings:
|
|
725
819
|
|
|
726
820
|
```tape
|
|
@@ -879,7 +973,8 @@ When exporting an episode, ScreenKit:
|
|
|
879
973
|
|
|
880
974
|
1. **Validates** project and episode configurations
|
|
881
975
|
2. **Generates voiceovers** from script files (if TTS enabled)
|
|
882
|
-
3. **Renders terminal recordings** from tape files using
|
|
976
|
+
3. **Renders terminal recordings** from tape files using
|
|
977
|
+
[Demo Tape](https://github.com/fnando/demotape)
|
|
883
978
|
4. **Combines segments** with crossfade transitions
|
|
884
979
|
5. **Adds intro/outro** scenes
|
|
885
980
|
6. **Overlays callouts** with animations
|
|
@@ -917,7 +1012,7 @@ be processed).
|
|
|
917
1012
|
### Visuals
|
|
918
1013
|
|
|
919
1014
|
- Use consistent branding across callouts
|
|
920
|
-
- Test callout
|
|
1015
|
+
- Test callout formats with `screenkit callout` command
|
|
921
1016
|
- PNG images with transparency work best for logos and watermarks
|
|
922
1017
|
|
|
923
1018
|
### Organization
|
|
@@ -953,7 +1048,7 @@ bundle exec screenkit ...
|
|
|
953
1048
|
|
|
954
1049
|
**TTS not working:**
|
|
955
1050
|
|
|
956
|
-
- For ElevenLabs: Set `--voice-api-key`
|
|
1051
|
+
- For ElevenLabs: Set `--voice-api-key`
|
|
957
1052
|
- For macOS `say`: Verify voice name with `say -v ?`
|
|
958
1053
|
|
|
959
1054
|
---
|
data/Dockerfile
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Stage 1: Download and extract fonts
|
|
2
|
+
FROM --platform=linux/amd64 alpine:latest AS fonts
|
|
3
|
+
RUN apk add --no-cache curl unzip
|
|
4
|
+
RUN mkdir /fonts && \
|
|
5
|
+
curl -sSL -o JetBrainsMono.zip https://github.com/ryanoasis/nerd-fonts/releases/download/v3.4.0/JetBrainsMono.zip && \
|
|
6
|
+
unzip -j JetBrainsMono.zip 'JetBrainsMonoNerdFontPropo-*.ttf' -d /fonts
|
|
7
|
+
|
|
8
|
+
# Stage 2: Download binaries
|
|
9
|
+
FROM --platform=linux/amd64 alpine:latest AS binaries
|
|
10
|
+
ARG SLIDES_VERSION=0.9.0
|
|
11
|
+
ARG TTYD_VERSION=1.7.7
|
|
12
|
+
ARG LL_VERSION=0.0.11
|
|
13
|
+
ARG BAT_VERSION=0.26.0
|
|
14
|
+
RUN apk add --no-cache curl
|
|
15
|
+
RUN mkdir /bin-download && cd /bin-download && \
|
|
16
|
+
curl -sSL https://github.com/maaslalani/slides/releases/download/v${SLIDES_VERSION}/slides_${SLIDES_VERSION}_linux_amd64.tar.gz | tar xz && \
|
|
17
|
+
curl -sSL https://github.com/tsl0922/ttyd/releases/download/${TTYD_VERSION}/ttyd.x86_64 > ttyd && \
|
|
18
|
+
curl -sSL https://github.com/fnando/ll/releases/download/v${LL_VERSION}/ll-x86_64-unknown-linux-gnu.tar.gz | tar xz && \
|
|
19
|
+
curl -sSL https://github.com/sharkdp/bat/releases/download/v${BAT_VERSION}/bat-v${BAT_VERSION}-x86_64-unknown-linux-musl.tar.gz | tar xz && \
|
|
20
|
+
mv bat-v${BAT_VERSION}-x86_64-unknown-linux-musl/bat . && \
|
|
21
|
+
chmod +x slides ttyd ll bat
|
|
22
|
+
|
|
23
|
+
# Stage 3: Final image
|
|
24
|
+
FROM --platform=linux/amd64 ruby:3.4-alpine
|
|
25
|
+
|
|
26
|
+
# Install runtime dependencies and build tools
|
|
27
|
+
RUN apk add --no-cache \
|
|
28
|
+
--repository=http://dl-cdn.alpinelinux.org/alpine/edge/main \
|
|
29
|
+
--repository=http://dl-cdn.alpinelinux.org/alpine/edge/community \
|
|
30
|
+
bash \
|
|
31
|
+
bash-completion \
|
|
32
|
+
build-base \
|
|
33
|
+
ca-certificates \
|
|
34
|
+
chromium \
|
|
35
|
+
chromium-chromedriver \
|
|
36
|
+
curl \
|
|
37
|
+
fish \
|
|
38
|
+
ffmpeg \
|
|
39
|
+
font-liberation \
|
|
40
|
+
font-noto \
|
|
41
|
+
font-noto-emoji \
|
|
42
|
+
freetype \
|
|
43
|
+
git \
|
|
44
|
+
gtk+3.0 \
|
|
45
|
+
harfbuzz \
|
|
46
|
+
imagemagick \
|
|
47
|
+
jq \
|
|
48
|
+
less \
|
|
49
|
+
mesa-gl \
|
|
50
|
+
nss \
|
|
51
|
+
python3 \
|
|
52
|
+
py3-pip \
|
|
53
|
+
py3-virtualenv \
|
|
54
|
+
sudo \
|
|
55
|
+
ttf-dejavu \
|
|
56
|
+
ttf-freefont \
|
|
57
|
+
udev \
|
|
58
|
+
zsh \
|
|
59
|
+
&& fc-cache -f
|
|
60
|
+
|
|
61
|
+
ARG USER=screenkit
|
|
62
|
+
ENV TERM=xterm-256color
|
|
63
|
+
ENV PATH="/venv/bin:/source/bin:/${USER}/bin:$PATH"
|
|
64
|
+
ENV CHROME_BIN=/usr/bin/chromium-browser
|
|
65
|
+
ENV CHROME_PATH=/usr/lib/chromium/
|
|
66
|
+
|
|
67
|
+
# Copy binaries and fonts from builder stages
|
|
68
|
+
COPY --from=binaries /bin-download/slides /usr/local/bin/slides
|
|
69
|
+
COPY --from=binaries /bin-download/ttyd /usr/local/bin/ttyd
|
|
70
|
+
COPY --from=binaries /bin-download/ll /usr/local/bin/ll
|
|
71
|
+
COPY --from=binaries /bin-download/bat /usr/local/bin/bat
|
|
72
|
+
COPY --from=fonts /fonts /usr/local/share/fonts
|
|
73
|
+
|
|
74
|
+
# Update font cache
|
|
75
|
+
RUN fc-cache -f
|
|
76
|
+
|
|
77
|
+
# Create user
|
|
78
|
+
RUN adduser -D -h /${USER} -s /bin/zsh -u 1001 ${USER} \
|
|
79
|
+
&& chown -R ${USER}:${USER} /${USER} \
|
|
80
|
+
&& echo "${USER} ALL=(ALL) NOPASSWD:ALL" > /etc/sudoers.d/${USER} \
|
|
81
|
+
&& chmod 0440 /etc/sudoers.d/${USER}
|
|
82
|
+
|
|
83
|
+
RUN mkdir -p /venv && chown -R ${USER}:${USER} /venv
|
|
84
|
+
RUN mkdir -p /${USER}-local && chown -R ${USER}:${USER} /${USER}-local
|
|
85
|
+
|
|
86
|
+
# Install screenkit gem
|
|
87
|
+
RUN gem install screenkit && \
|
|
88
|
+
mkdir -p /usr/share/bash-completion/completions && \
|
|
89
|
+
mkdir -p /usr/share/zsh/site-functions && \
|
|
90
|
+
mkdir -p /usr/share/fish/vendor_completions.d && \
|
|
91
|
+
screenkit completion --shell bash > /usr/share/bash-completion/completions/screenkit && \
|
|
92
|
+
screenkit completion --shell zsh > /usr/share/zsh/site-functions/_screenkit && \
|
|
93
|
+
screenkit completion --shell fish > /usr/share/fish/vendor_completions.d/screenkit.fish && \
|
|
94
|
+
echo 'autoload -Uz compinit && compinit' >> /etc/zsh/zshrc && \
|
|
95
|
+
echo 'source /usr/share/bash-completion/bash_completion' >> /etc/bash/bashrc && \
|
|
96
|
+
apk del build-base
|
|
97
|
+
|
|
98
|
+
USER ${USER}
|
|
99
|
+
WORKDIR /${USER}
|
|
100
|
+
|
|
101
|
+
# Create Python virtual environment
|
|
102
|
+
RUN python3 -m venv /venv
|
|
103
|
+
RUN /venv/bin/pip install ffmpeg-normalize
|
|
104
|
+
|
|
105
|
+
WORKDIR /source
|
|
106
|
+
|
|
107
|
+
ENTRYPOINT [ "screenkit" ]
|
data/lib/screen_kit.rb
CHANGED
|
@@ -19,6 +19,7 @@ module ScreenKit
|
|
|
19
19
|
require_relative "screenkit/content_type"
|
|
20
20
|
require_relative "screenkit/anchor"
|
|
21
21
|
require_relative "screenkit/banner"
|
|
22
|
+
require_relative "screenkit/time_formatter"
|
|
22
23
|
require_relative "screenkit/spacing"
|
|
23
24
|
require_relative "screenkit/watermark"
|
|
24
25
|
require_relative "screenkit/spinner"
|
|
@@ -31,17 +32,15 @@ module ScreenKit
|
|
|
31
32
|
require_relative "screenkit/config/episode"
|
|
32
33
|
require_relative "screenkit/callout"
|
|
33
34
|
require_relative "screenkit/callout/text_style"
|
|
35
|
+
require_relative "screenkit/callout/styles/base"
|
|
34
36
|
require_relative "screenkit/transition"
|
|
35
37
|
require_relative "screenkit/parallel_processor"
|
|
36
|
-
require_relative "screenkit/callout/styles/base"
|
|
37
|
-
require_relative "screenkit/callout/styles/default"
|
|
38
38
|
require_relative "screenkit/cli"
|
|
39
39
|
require_relative "screenkit/cli/base"
|
|
40
40
|
require_relative "screenkit/cli/episode"
|
|
41
41
|
require_relative "screenkit/cli/root"
|
|
42
|
-
require_relative "screenkit/tts/say"
|
|
43
|
-
require_relative "screenkit/tts/eleven_labs"
|
|
44
42
|
require_relative "screenkit/animation_filters"
|
|
43
|
+
require_relative "screenkit/tts/base"
|
|
45
44
|
require_relative "screenkit/path_lookup"
|
|
46
45
|
require_relative "screenkit/sound"
|
|
47
46
|
require_relative "screenkit/utils"
|
|
@@ -54,6 +53,18 @@ module ScreenKit
|
|
|
54
53
|
require_relative "screenkit/exporter/image"
|
|
55
54
|
require_relative "screenkit/exporter/video"
|
|
56
55
|
|
|
56
|
+
require_files = lambda do |pattern|
|
|
57
|
+
Gem.find_files_from_load_path(pattern).each do |path|
|
|
58
|
+
next if path.include?("test")
|
|
59
|
+
|
|
60
|
+
require(path)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Load all files that may be available as plugins.
|
|
65
|
+
require_files.call("screenkit/callout/styles/*.rb")
|
|
66
|
+
require_files.call("screenkit/tts/*.rb")
|
|
67
|
+
|
|
57
68
|
def self.root_dir
|
|
58
69
|
@root_dir ||= Pathname(__dir__)
|
|
59
70
|
end
|
|
@@ -66,16 +77,4 @@ module ScreenKit
|
|
|
66
77
|
|
|
67
78
|
# Raised when a file entry is not found in the lookup.
|
|
68
79
|
FileEntryNotFoundError = Class.new(StandardError)
|
|
69
|
-
|
|
70
|
-
require_files = lambda do |pattern|
|
|
71
|
-
Gem.find_files_from_load_path(pattern).each do |path|
|
|
72
|
-
next if path.include?("test")
|
|
73
|
-
|
|
74
|
-
require(path)
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
|
|
78
|
-
# Load all files that may be available as plugins.
|
|
79
|
-
require_files.call("screenkit/callout/styles/*.rb")
|
|
80
|
-
require_files.call("screenkit/callout/tts/*.rb")
|
|
81
80
|
end
|
|
@@ -110,5 +110,21 @@ module ScreenKit
|
|
|
110
110
|
|
|
111
111
|
{video: filters, out_start:}
|
|
112
112
|
end
|
|
113
|
+
|
|
114
|
+
def video
|
|
115
|
+
filters = []
|
|
116
|
+
|
|
117
|
+
# For video callouts:
|
|
118
|
+
# Add transparent padding at start to delay, then overlay
|
|
119
|
+
filters <<
|
|
120
|
+
"[#{callout_index}:v]tpad=start_duration=#{starts_at}:" \
|
|
121
|
+
"color=black@0.0[callout#{index}_delayed]"
|
|
122
|
+
|
|
123
|
+
filters <<
|
|
124
|
+
"[#{input_stream}][callout#{index}_delayed]overlay=x=#{x}:y=#{y}:" \
|
|
125
|
+
"eof_action=pass[#{output_stream}]"
|
|
126
|
+
|
|
127
|
+
{video: filters, out_start:}
|
|
128
|
+
end
|
|
113
129
|
end
|
|
114
130
|
end
|
|
@@ -4,6 +4,18 @@ module ScreenKit
|
|
|
4
4
|
class Callout
|
|
5
5
|
module Styles
|
|
6
6
|
class Base
|
|
7
|
+
attr_reader :source, :output_path, :log_path
|
|
8
|
+
attr_accessor :options
|
|
9
|
+
|
|
10
|
+
extend SchemaValidator
|
|
11
|
+
|
|
12
|
+
def initialize(source:, output_path:, log_path: nil, **options)
|
|
13
|
+
@source = source
|
|
14
|
+
@output_path = output_path
|
|
15
|
+
@log_path = log_path
|
|
16
|
+
@options = options
|
|
17
|
+
end
|
|
18
|
+
|
|
7
19
|
def text_wrap(text, max_width:, font_size:)
|
|
8
20
|
words = text.to_s.split(/\s+/)
|
|
9
21
|
width_factor = 0.6
|