screenkit 0.0.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.
Files changed (142) hide show
  1. checksums.yaml +7 -0
  2. data/.github/CODEOWNERS +4 -0
  3. data/.github/FUNDING.yml +4 -0
  4. data/.github/ISSUE_TEMPLATE/bug_report.md +41 -0
  5. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  6. data/.github/ISSUE_TEMPLATE/feature_request.md +23 -0
  7. data/.github/PULL_REQUEST_TEMPLATE.md +38 -0
  8. data/.github/dependabot.yml +15 -0
  9. data/.github/workflows/ruby-tests.yml +51 -0
  10. data/.gitignore +12 -0
  11. data/.rubocop.yml +14 -0
  12. data/CHANGELOG.md +16 -0
  13. data/CODE_OF_CONDUCT.md +74 -0
  14. data/CONTRIBUTING.md +80 -0
  15. data/DOCUMENTATION.md +972 -0
  16. data/Gemfile +5 -0
  17. data/LICENSE.md +20 -0
  18. data/README.md +49 -0
  19. data/Rakefile +15 -0
  20. data/bin/console +16 -0
  21. data/bin/setup +10 -0
  22. data/exe/screenkit +5 -0
  23. data/lib/screen_kit.rb +79 -0
  24. data/lib/screenkit/anchor.rb +19 -0
  25. data/lib/screenkit/animation_filters.rb +114 -0
  26. data/lib/screenkit/banner.rb +46 -0
  27. data/lib/screenkit/callout/styles/base.rb +101 -0
  28. data/lib/screenkit/callout/styles/default.rb +144 -0
  29. data/lib/screenkit/callout/styles/inline_block.rb +123 -0
  30. data/lib/screenkit/callout/text_style.rb +44 -0
  31. data/lib/screenkit/callout.rb +98 -0
  32. data/lib/screenkit/cli/base.rb +24 -0
  33. data/lib/screenkit/cli/episode.rb +78 -0
  34. data/lib/screenkit/cli/root.rb +73 -0
  35. data/lib/screenkit/cli.rb +9 -0
  36. data/lib/screenkit/config/base.rb +51 -0
  37. data/lib/screenkit/config/episode.rb +42 -0
  38. data/lib/screenkit/config/project.rb +47 -0
  39. data/lib/screenkit/content_type.rb +12 -0
  40. data/lib/screenkit/core_ext/json.rb +47 -0
  41. data/lib/screenkit/core_ext/string.rb +28 -0
  42. data/lib/screenkit/exporter/demotape.rb +26 -0
  43. data/lib/screenkit/exporter/episode.rb +565 -0
  44. data/lib/screenkit/exporter/image.rb +31 -0
  45. data/lib/screenkit/exporter/intro.rb +261 -0
  46. data/lib/screenkit/exporter/outro.rb +183 -0
  47. data/lib/screenkit/exporter/segment.rb +258 -0
  48. data/lib/screenkit/exporter/video.rb +33 -0
  49. data/lib/screenkit/generators/episode/config.yml.erb +106 -0
  50. data/lib/screenkit/generators/episode/content/001.tape +4 -0
  51. data/lib/screenkit/generators/episode/scripts/001.txt +1 -0
  52. data/lib/screenkit/generators/episode.rb +31 -0
  53. data/lib/screenkit/generators/project/Gemfile.erb +7 -0
  54. data/lib/screenkit/generators/project/resources/backtracks/default.aac +0 -0
  55. data/lib/screenkit/generators/project/resources/fonts/opensans/OFL.txt +93 -0
  56. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-Bold.ttf +0 -0
  57. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-BoldItalic.ttf +0 -0
  58. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-ExtraBold.ttf +0 -0
  59. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-ExtraBoldItalic.ttf +0 -0
  60. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-Italic.ttf +0 -0
  61. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-Light.ttf +0 -0
  62. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-LightItalic.ttf +0 -0
  63. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-Medium.ttf +0 -0
  64. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-MediumItalic.ttf +0 -0
  65. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-Regular.ttf +0 -0
  66. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-SemiBold.ttf +0 -0
  67. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans-SemiBoldItalic.ttf +0 -0
  68. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-Bold.ttf +0 -0
  69. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-BoldItalic.ttf +0 -0
  70. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-ExtraBold.ttf +0 -0
  71. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-ExtraBoldItalic.ttf +0 -0
  72. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-Italic.ttf +0 -0
  73. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-Light.ttf +0 -0
  74. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-LightItalic.ttf +0 -0
  75. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-Medium.ttf +0 -0
  76. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-MediumItalic.ttf +0 -0
  77. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-Regular.ttf +0 -0
  78. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-SemiBold.ttf +0 -0
  79. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_Condensed-SemiBoldItalic.ttf +0 -0
  80. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-Bold.ttf +0 -0
  81. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-BoldItalic.ttf +0 -0
  82. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-ExtraBold.ttf +0 -0
  83. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-ExtraBoldItalic.ttf +0 -0
  84. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-Italic.ttf +0 -0
  85. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-Light.ttf +0 -0
  86. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-LightItalic.ttf +0 -0
  87. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-Medium.ttf +0 -0
  88. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-MediumItalic.ttf +0 -0
  89. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-Regular.ttf +0 -0
  90. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-SemiBold.ttf +0 -0
  91. data/lib/screenkit/generators/project/resources/fonts/opensans/OpenSans_SemiCondensed-SemiBoldItalic.ttf +0 -0
  92. data/lib/screenkit/generators/project/resources/fonts/opensans/README.txt +100 -0
  93. data/lib/screenkit/generators/project/resources/images/logo.png +0 -0
  94. data/lib/screenkit/generators/project/resources/images/watermark.png +0 -0
  95. data/lib/screenkit/generators/project/resources/sounds/chime.mp3 +0 -0
  96. data/lib/screenkit/generators/project/resources/sounds/pop.mp3 +0 -0
  97. data/lib/screenkit/generators/project/resources/sounds/whoosh.mp3 +0 -0
  98. data/lib/screenkit/generators/project/screenkit.yml +189 -0
  99. data/lib/screenkit/generators/project.rb +34 -0
  100. data/lib/screenkit/logfile.rb +33 -0
  101. data/lib/screenkit/parallel_processor.rb +50 -0
  102. data/lib/screenkit/path_lookup.rb +27 -0
  103. data/lib/screenkit/resources/mute.mp3 +0 -0
  104. data/lib/screenkit/resources/transparent.png +0 -0
  105. data/lib/screenkit/schema_validator.rb +14 -0
  106. data/lib/screenkit/schemas/callouts/default.json +44 -0
  107. data/lib/screenkit/schemas/callouts/inline_block.json +20 -0
  108. data/lib/screenkit/schemas/episode.json +74 -0
  109. data/lib/screenkit/schemas/project.json +37 -0
  110. data/lib/screenkit/schemas/refs/anchor.json +17 -0
  111. data/lib/screenkit/schemas/refs/animation.json +7 -0
  112. data/lib/screenkit/schemas/refs/background.json +14 -0
  113. data/lib/screenkit/schemas/refs/callout.json +27 -0
  114. data/lib/screenkit/schemas/refs/color.json +7 -0
  115. data/lib/screenkit/schemas/refs/directory.json +20 -0
  116. data/lib/screenkit/schemas/refs/intro.json +30 -0
  117. data/lib/screenkit/schemas/refs/logo.json +26 -0
  118. data/lib/screenkit/schemas/refs/outro.json +26 -0
  119. data/lib/screenkit/schemas/refs/position.json +38 -0
  120. data/lib/screenkit/schemas/refs/scenes.json +27 -0
  121. data/lib/screenkit/schemas/refs/size.json +19 -0
  122. data/lib/screenkit/schemas/refs/sound.json +36 -0
  123. data/lib/screenkit/schemas/refs/spacing.json +22 -0
  124. data/lib/screenkit/schemas/refs/text_style.json +18 -0
  125. data/lib/screenkit/schemas/refs/transition.json +15 -0
  126. data/lib/screenkit/schemas/refs/tts.json +47 -0
  127. data/lib/screenkit/schemas/refs/watermark.json +18 -0
  128. data/lib/screenkit/schemas/tts/elevenlabs.json +67 -0
  129. data/lib/screenkit/schemas/tts/say.json +16 -0
  130. data/lib/screenkit/shell.rb +58 -0
  131. data/lib/screenkit/sound.rb +44 -0
  132. data/lib/screenkit/spacing.rb +23 -0
  133. data/lib/screenkit/spinner.rb +39 -0
  134. data/lib/screenkit/transition.rb +16 -0
  135. data/lib/screenkit/tts/eleven_labs.rb +51 -0
  136. data/lib/screenkit/tts/say.rb +31 -0
  137. data/lib/screenkit/utils.rb +87 -0
  138. data/lib/screenkit/version.rb +5 -0
  139. data/lib/screenkit/watermark.rb +34 -0
  140. data/lib/screenkit.rb +3 -0
  141. data/screenkit.gemspec +56 -0
  142. metadata +426 -0
@@ -0,0 +1,189 @@
1
+ ---
2
+ # yaml-language-server: $schema=../../schemas/project.json
3
+
4
+ # ScreenKit project configuration file.
5
+ schema: 1
6
+
7
+ # The episodes directory is where the source files for each episode are stored.
8
+ # A new episode can be generated with `screenkit episode new`.
9
+ #
10
+ # The episode directory name can include placeholders:
11
+ # - %{episode_number}: The episode number
12
+ # - %{episode_slug}: A URL-friendly slug for the episode title
13
+ # - %{date}: The current timestamp in `yyyy-mm-dd` format.
14
+ #
15
+ # You can have padded episodes number by using a format string that looks like
16
+ # `%<episode_number>03d` (e.g. `001`).
17
+ episode_dir: episodes/%<episode_number>03d-%{episode_slug}
18
+
19
+ # The resources directory contains additional resource files used in the video.
20
+ # These can include images, sounds, fonts, etc.
21
+ # When defining your configuration, you can just specify the partial path. For
22
+ # instance, if you have an image at `resources/images/picture.png`, you can just
23
+ # refer to it as `images/picture.png`.
24
+ #
25
+ # You can also specify absolute paths, like system font directories.
26
+ #
27
+ # To point to the episode directory, use the placeholder `%{episode_dir}`.
28
+ resources_dir:
29
+ - .
30
+ - "%{episode_dir}"
31
+ - resources
32
+ - "%{episode_dir}/resources"
33
+ - resources/backtracks
34
+ - "%{episode_dir}/resources/backtracks"
35
+ - resources/sounds
36
+ - "%{episode_dir}/resources/sounds"
37
+ - resources/images
38
+ - "%{episode_dir}/resources/images"
39
+ - resources/fonts
40
+ - "%{episode_dir}/resources/fonts"
41
+ - resources
42
+ - "%{episode_dir}/resources"
43
+ - ~/Library/Fonts
44
+ - /Library/Fonts
45
+ - /System/Library/Fonts
46
+ - ~/.fonts
47
+ - ~/.local/share/fonts
48
+ - /usr/share/fonts
49
+ - /usr/local/share/fonts
50
+ - /opt/share/fonts
51
+
52
+ # The output directory is where the generated video files will be saved.
53
+ # You can change this to any directory you prefer.
54
+ #
55
+ # To point to the episode directory's name, use the placeholder
56
+ # `%{episode_dirname}`.
57
+ output_dir: output/%{episode_dirname}
58
+
59
+ # Set the backtrack file or directory.
60
+ # When a directory is specified, a random backtrack will be chosen from the
61
+ # directory.
62
+ # When a file is specified, that specific backtrack will be used instead.
63
+ #
64
+ # The entry is searched by using the `resorces_dir` config.
65
+ #
66
+ # You can disable the backtrack by setting this to `false`.
67
+ backtrack: backtracks/
68
+
69
+ # Render a watermark.
70
+ # This is useful for branding or copyright purposes.
71
+ # The watermark is omitted from the intro and outro scenes.
72
+ # To disable the watermark, use `watermark: false`.
73
+ watermark:
74
+ path: "watermark.png"
75
+ anchor: [right, bottom]
76
+ margin: 100
77
+
78
+ # TTS configuration.
79
+ # To disable voiceover entirely, set `tts: false`.
80
+ # tts:
81
+ # engine: elevenlabs
82
+ # voice_id: 56AoDkrOh6qfVPDXZ7Pt
83
+ # language_code: en
84
+ # voice_settings:
85
+ # speed: 0.9
86
+ # stability: 0.5
87
+ # similarity: 0.75
88
+ # style: 0.0
89
+ tts:
90
+ engine: say
91
+ rate: 150
92
+
93
+ # Scene configurations define how different scenes in the video are rendered.
94
+ # There are three types of scenes: intro, outro, and segment.
95
+ # - Intro: The opening scene of the video, typically featuring the logo.
96
+ # - Outro: The closing scene of the video.
97
+ # - Segment: The main content scenes of the video.
98
+ scenes:
99
+ intro:
100
+ # The duration of the intro scene in seconds.
101
+ duration: 5.5
102
+
103
+ # The fade-in duration in seconds.
104
+ fade_in: 0
105
+
106
+ # The fade-out duration in seconds.
107
+ fade_out: 0.5
108
+
109
+ # The background color/image of the intro scene.
110
+ background: "#100f50"
111
+
112
+ # The title text to be displayed in the intro scene.
113
+ title:
114
+ x: 100
115
+ y: 300
116
+ font_path: opensans/OpenSans-ExtraBold.ttf
117
+ size: 144
118
+ color: "#ffffff"
119
+
120
+ # The logo to be displayed in the video intro.
121
+ # Works best with a transparent PNG file in high resolution (at least 2x the
122
+ # size it'll be displayed).
123
+ logo:
124
+ path: logo.png
125
+ x: 100
126
+ y: 200
127
+ width: 300
128
+
129
+ # The sound to be played along with the logo in the intro.
130
+ # This must correspond to a sound file in the sounds directory, with any
131
+ # audio extension (e.g. mp3, m4a, wav).
132
+ sound: false
133
+
134
+ outro:
135
+ # The duration of the outro scene in seconds.
136
+ duration: 5.5
137
+
138
+ # The fade-in duration in seconds.
139
+ fade_in: 0.5
140
+
141
+ # The fade-out duration in seconds.
142
+ fade_out: 0.5
143
+
144
+ # The background color/image of the outro scene.
145
+ background: "#100f50"
146
+
147
+ # The sound to be played along with the logo in the outro.
148
+ sound: chime.mp3
149
+
150
+ # The logo to be displayed in the video outro.
151
+ logo:
152
+ path: logo.png
153
+ x: center
154
+ y: center
155
+ width: 300
156
+
157
+ segment:
158
+ # The duration of the crossover transition between segments in seconds.
159
+ crossfade_duration: 0.5
160
+
161
+ # Callout configurations define the appearance and behavior of callouts used
162
+ # in the video. Callouts are visual elements that highlight important
163
+ # information. Each callout type can have its own settings for icon, background,
164
+ # text styles, animations, and sounds.
165
+ callouts:
166
+ info:
167
+ # yaml-language-server: $schema=../../schemas/callouts/default.json
168
+ background_color: "#ffff00"
169
+ shadow: "#2242d3"
170
+ title_style:
171
+ color: "#000000"
172
+ size: 40
173
+ font_path: opensans/OpenSans-ExtraBold.ttf
174
+ body_style:
175
+ color: "#000000"
176
+ size: 32
177
+ font_path: opensans/OpenSans-Semibold.ttf
178
+ margin: 100
179
+ padding: 50
180
+ anchor: [left, bottom]
181
+ animation: fade
182
+ in_transition:
183
+ duration: 0.4
184
+ sound: pop.mp3
185
+ out_transition:
186
+ duration: 0.3
187
+ sound:
188
+ path: pop.mp3
189
+ volume: 0.7
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScreenKit
4
+ module Generators
5
+ class Project < Thor::Group
6
+ include Thor::Actions
7
+
8
+ attr_accessor :options
9
+
10
+ def self.source_root
11
+ File.join(__dir__, "project")
12
+ end
13
+
14
+ def create_project_dir
15
+ template "Gemfile.erb", "Gemfile"
16
+ end
17
+
18
+ def copy_files
19
+ copy_file "screenkit.yml"
20
+ directory "resources", exclude_pattern: /DS_Store/
21
+ end
22
+
23
+ def bundle_install
24
+ in_root do
25
+ run "bundle install"
26
+ end
27
+ end
28
+
29
+ no_commands do
30
+ # Add helper methods here
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,33 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScreenKit
4
+ class Logfile
5
+ attr_reader :root_dir, :basename, :mutex
6
+ attr_accessor :index
7
+
8
+ def initialize(root_dir)
9
+ @root_dir = root_dir
10
+ @index = 0
11
+ @mutex = Mutex.new
12
+ end
13
+
14
+ def create(*args)
15
+ args.unshift(mutex.synchronize { format("%04d", index) })
16
+ mutex.synchronize { self.index += 1 }
17
+
18
+ Pathname(root_dir).join("#{args.join('-')}.txt")
19
+ end
20
+
21
+ def log(*args)
22
+ message = args.pop
23
+ path = create(*args)
24
+ FileUtils.mkdir_p(File.dirname(path))
25
+ File.open(path, "w") { it << message.to_s }
26
+ end
27
+
28
+ def json_log(*args)
29
+ message = args.pop
30
+ log(*args, JSON.pretty_generate(message))
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScreenKit
4
+ class ParallelProcessor
5
+ attr_reader :spinner, :list, :message, :mutex, :count, :log_path
6
+ attr_accessor :progress
7
+
8
+ def initialize(spinner:, list:, message:, log_path: nil)
9
+ @list = list
10
+ @message = message
11
+ @spinner = spinner
12
+ @mutex = Mutex.new
13
+ @progress = 0
14
+ @count = list.size
15
+ @log_path = log_path
16
+ end
17
+
18
+ def run(&block)
19
+ started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
20
+ indexed_list = list.map.with_index {|item, index| [item, index] }
21
+ arity = block.arity
22
+
23
+ indexed_list.each_slice(Etc.nprocessors) do |slice|
24
+ threads = slice.map do |args|
25
+ thread = Thread.new do
26
+ yield(*args.take([1, arity].max), log_path:)
27
+ update_progress
28
+ end
29
+
30
+ thread.abort_on_exception = true
31
+ thread
32
+ end
33
+
34
+ threads.each(&:join)
35
+ end
36
+
37
+ spinner.stop
38
+
39
+ ended_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
40
+ ended_at - started_at
41
+ end
42
+
43
+ def update_progress
44
+ mutex.synchronize do
45
+ self.progress += 1
46
+ spinner.update(format(message, count:, progress:))
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScreenKit
4
+ class PathLookup
5
+ # The directories to search for files.
6
+ attr_reader :dirs
7
+
8
+ def initialize(*dirs)
9
+ @dirs = dirs.map { Pathname(it) }
10
+ end
11
+
12
+ # Search for the given path in the configured directories.
13
+ # @param path [String, Pathname] The relative path to search for.
14
+ # @return [Pathname, nil] The found path or nil if not found.
15
+ def search(path, default: nil)
16
+ dirs.each do |dir|
17
+ candidate = dir.join(path)
18
+ return candidate if candidate.exist?
19
+ end
20
+
21
+ return default if default
22
+
23
+ raise FileEntryNotFoundError,
24
+ %[No file entry found for #{path.to_s.inspect}]
25
+ end
26
+ end
27
+ end
Binary file
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ScreenKit
4
+ module SchemaValidator
5
+ def validate!(attributes)
6
+ errors = JSON::Validator
7
+ .fully_validate("file://#{schema_path}", attributes)
8
+
9
+ return if errors.empty?
10
+
11
+ raise ArgumentError, "Invalid attributes: #{errors.first}"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,44 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/callouts/basic.json",
4
+ "title": "Basic Callout",
5
+ "type": "object",
6
+ "required": [
7
+ "background_color",
8
+ "body_style",
9
+ "padding",
10
+ "shadow",
11
+ "title_style"
12
+ ],
13
+ "properties": {
14
+ "width": {
15
+ "type": "number",
16
+ "description": "The callout width"
17
+ },
18
+ "background_color": {
19
+ "$ref": "../refs/color.json"
20
+ },
21
+ "shadow": {
22
+ "oneOf": [
23
+ { "type": "boolean", "enum": [false] },
24
+ { "type": "string", "$ref": "../refs/color.json" },
25
+ {
26
+ "type": "object",
27
+ "properties": {
28
+ "color": { "$ref": "../refs/color.json" },
29
+ "offset": { "type": "integer" }
30
+ }
31
+ }
32
+ ]
33
+ },
34
+ "title_style": {
35
+ "$ref": "../refs/text_style.json"
36
+ },
37
+ "body_style": {
38
+ "$ref": "../refs/text_style.json"
39
+ },
40
+ "padding": {
41
+ "$ref": "../refs/spacing.json"
42
+ }
43
+ }
44
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/callouts/inline_block.json",
4
+ "title": "Inline Block Callout",
5
+ "type": "object",
6
+ "required": ["background_color", "text_style"],
7
+ "properties": {
8
+ "background_color": { "$ref": "../refs/color.json" },
9
+ "width": {
10
+ "type": "number",
11
+ "description": "The callout width"
12
+ },
13
+ "text_style": {
14
+ "$ref": "../refs/text_style.json"
15
+ },
16
+ "padding": {
17
+ "$ref": "../refs/spacing.json"
18
+ }
19
+ }
20
+ }
@@ -0,0 +1,74 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/episode.json",
4
+ "title": "ScreenKit Episode Configuration",
5
+ "description": "Schema for ScreenKit episode configuration file (config.yml)",
6
+ "type": "object",
7
+ "required": ["title"],
8
+ "properties": {
9
+ "backtrack": { "$ref": "refs/sound.json" },
10
+ "scenes": { "$ref": "refs/scenes.json" },
11
+ "tts": { "$ref": "refs/tts.json" },
12
+ "watermark": { "$ref": "refs/watermark.json" },
13
+ "title": {
14
+ "type": "string",
15
+ "description": "The episode title",
16
+ "minLength": 1,
17
+ "pattern": "\\S"
18
+ },
19
+ "callouts": {
20
+ "type": "array",
21
+ "description": "List of callouts to be used in the episode",
22
+ "items": {
23
+ "type": "object",
24
+ "required": ["type", "starts_at", "duration"],
25
+ "additionalProperties": true,
26
+ "properties": {
27
+ "type": {
28
+ "type": "string",
29
+ "description": "Callout type identifier",
30
+ "minLength": 1,
31
+ "pattern": "\\S"
32
+ },
33
+ "starts_at": {
34
+ "oneOf": [
35
+ {
36
+ "type": "string",
37
+ "description": "Callout start time in HH:MM:SS format (e.g. 00:01:30)"
38
+ },
39
+ {
40
+ "type": "number",
41
+ "description": "Callout start time in seconds (e.g. 90)"
42
+ }
43
+ ]
44
+ },
45
+ "duration": {
46
+ "oneOf": [
47
+ {
48
+ "type": "string",
49
+ "description": "Callout duration time (e.g. 5s)",
50
+ "pattern": "/^\\d+(s|m|h)$/"
51
+ },
52
+ {
53
+ "type": "number",
54
+ "description": "Callout duration time in seconds (e.g. 5)"
55
+ }
56
+ ]
57
+ },
58
+ "width": {
59
+ "oneOf": [
60
+ {
61
+ "type": "string",
62
+ "description": "Callout width in percentage (e.g. 50%)"
63
+ },
64
+ {
65
+ "type": "number",
66
+ "description": "Callout width in pixels (e.g. 300)"
67
+ }
68
+ ]
69
+ }
70
+ }
71
+ }
72
+ }
73
+ }
74
+ }
@@ -0,0 +1,37 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/project.json",
4
+ "title": "ScreenKit Project Configuration",
5
+ "description": "Schema for ScreenKit project configuration file (screenkit.yml)",
6
+ "type": "object",
7
+ "required": ["schema", "resources_dir", "episode_dir", "output_dir"],
8
+ "properties": {
9
+ "resources_dir": { "$ref": "refs/directory.json" },
10
+ "backtrack": { "$ref": "refs/sound.json" },
11
+ "tts": { "$ref": "refs/tts.json" },
12
+ "watermark": { "$ref": "refs/watermark.json" },
13
+ "scenes": { "$ref": "refs/scenes.json" },
14
+ "schema": {
15
+ "type": "integer",
16
+ "description": "The schema version number",
17
+ "enum": [1]
18
+ },
19
+ "episode_dir": {
20
+ "type": "string",
21
+ "description": "Directory where episode source files are stored. Supports placeholders like %{episode_number}, %{episode_slug} and %{date}.",
22
+ "$ref": "refs/directory.json"
23
+ },
24
+ "output_dir": {
25
+ "type": "string",
26
+ "description": "Directory where generated video files will be saved. Supports placeholders like %{episode_number}, %{episode_slug} and %{date}.",
27
+ "format": "uri"
28
+ },
29
+ "callouts": {
30
+ "type": "object",
31
+ "additionalProperties": {
32
+ "$ref": "refs/callout.json"
33
+ }
34
+ }
35
+ },
36
+ "additionalProperties": false
37
+ }
@@ -0,0 +1,17 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/anchor.json",
4
+ "title": "Anchor",
5
+ "type": "array",
6
+ "description": "Anchor position [horizontal, vertical]",
7
+ "items": [
8
+ {
9
+ "type": "string",
10
+ "enum": ["left", "center", "right"]
11
+ },
12
+ {
13
+ "type": "string",
14
+ "enum": ["top", "center", "bottom"]
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/refs/animation.json",
4
+ "title": "Animation Type",
5
+ "type": "string",
6
+ "enum": ["slide", "fade"]
7
+ }
@@ -0,0 +1,14 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/refs/background.json",
4
+ "title": "Background",
5
+ "anyOf": [
6
+ {
7
+ "type": "string",
8
+ "format": "uri"
9
+ },
10
+ {
11
+ "$ref": "color.json"
12
+ }
13
+ ]
14
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/callout.json",
4
+ "title": "Callout",
5
+ "type": "object",
6
+ "required": [
7
+ "in_transition",
8
+ "out_transition",
9
+ "anchor",
10
+ "margin",
11
+ "animation"
12
+ ],
13
+ "properties": {
14
+ "in_transition": { "$ref": "transition.json" },
15
+ "out_transition": { "$ref": "transition.json" },
16
+ "animation": { "$ref": "animation.json" },
17
+ "margin": { "$ref": "spacing.json" },
18
+ "style": {
19
+ "type": "string",
20
+ "description": "Callout style name (defaults to 'default')",
21
+ "default": "default"
22
+ },
23
+ "anchor": {
24
+ "$ref": "anchor.json"
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,7 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/refs/color.json",
4
+ "title": "Color type with optional alpha channel",
5
+ "type": "string",
6
+ "pattern": "^#[0-9a-fA-F]{6}([0-9a-fA-F]{2})?$"
7
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/project.json",
4
+ "title": "Directory",
5
+ "oneOf": [
6
+ {
7
+ "type": "string",
8
+ "description": "Directory containing background music files",
9
+ "format": "uri"
10
+ },
11
+ {
12
+ "type": "array",
13
+ "description": "List of directories containing background music files",
14
+ "items": {
15
+ "type": "string",
16
+ "format": "uri"
17
+ }
18
+ }
19
+ ]
20
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-04/schema#",
3
+ "$id": "https://github.com/fnando/screenkit/schemas/refs/intro.json",
4
+ "title": "Intro",
5
+ "properties": {
6
+ "duration": {
7
+ "type": "number",
8
+ "description": "Duration of the intro scene in seconds",
9
+ "minimum": 0
10
+ },
11
+ "fade_in": {
12
+ "type": "number",
13
+ "description": "Fade-in duration in seconds",
14
+ "minimum": 0
15
+ },
16
+ "fade_out": {
17
+ "type": "number",
18
+ "description": "Fade-out duration in seconds",
19
+ "minimum": 0
20
+ },
21
+ "title": {
22
+ "type": "object",
23
+ "description": "Title configuration",
24
+ "allOf": [{ "$ref": "text_style.json" }, { "$ref": "position.json" }]
25
+ },
26
+ "background": { "$ref": "background.json" },
27
+ "logo": { "$ref": "logo.json" },
28
+ "sound": { "$ref": "sound.json" }
29
+ }
30
+ }