fli_video 0.1.0 → 0.1.2
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/{scripts/03-get-technical-design-and-features.rb → .builders/generators/back/scripts/01-get-technical-design-and-feature-list.rb} +5 -0
- data/{scripts/02-get-features-and-components.rb → .builders/generators/back/scripts/02-get-feature-list-and-components.rb} +4 -0
- data/{scripts/01-get-structure.rb → .builders/generators/back/scripts/03-get-structure.rb} +23 -3
- data/.builders/generators/back/scripts/generated/application-structure.json +231 -0
- data/.builders/generators/back/scripts/generated/features-and-components.md +988 -0
- data/.builders/generators/back/scripts/generated/technical-design-and-features.md +424 -0
- data/.builders/klues/add_episode.klue +1 -1
- data/.builders/klues/create_project.klue +1 -1
- data/.builders/klues/move_to_trash.klue +8 -2
- data/.rubocop.yml +5 -1
- data/CHANGELOG.md +15 -0
- data/README.md +1 -1
- data/docs/feature-list.md +1 -0
- data/docs/generated/application-structure.json +2 -6
- data/docs/generated/features-and-components.md +36 -30
- data/docs/generated/technical-design-and-features.md +25 -8
- data/docs/project-new.md +184 -0
- data/docs/technical-specifications.md +14 -1
- data/lib/fli_video/version.rb +1 -1
- data/package-lock.json +2 -2
- data/package.json +1 -1
- data/scripts/01-get-technical-design-and-feature-list.md +5 -0
- data/scripts/01-get-technical-design-and-feature-list.rb +39 -0
- data/scripts/02-get-feature-list-and-components.md +26 -0
- data/scripts/02-get-feature-list-and-components.rb +56 -0
- data/scripts/03-get-code-structure.md +33 -0
- data/scripts/03-get-code-structure.rb +73 -0
- metadata +15 -5
@@ -0,0 +1,988 @@
|
|
1
|
+
## Features
|
2
|
+
|
3
|
+
### Feature <-> DSL GPTs
|
4
|
+
https://chat.openai.com/g/g-AyFi0UOXn-code-simplifier
|
5
|
+
|
6
|
+
**Global Configuration**
|
7
|
+
Access and apply global configuration settings for video asset management and state consistency.
|
8
|
+
|
9
|
+
**Project Configuration**
|
10
|
+
Access and apply video or episode settings and state. Infers project settings from existing project folders and files.
|
11
|
+
|
12
|
+
**CLI Project Commands**
|
13
|
+
Efficiently execute and manage video project commands using a command-line interface, enhancing control and flexibility in project handling.
|
14
|
+
|
15
|
+
**FileWatch Processor**
|
16
|
+
Utilize a FileWatch processor to automate file event responses, directing new recordings to designated folders for efficient content management.
|
17
|
+
|
18
|
+
**Create Project**
|
19
|
+
Setup a new video project for standalone YouTube video or Podcast.
|
20
|
+
|
21
|
+
**Add Episode**
|
22
|
+
Add a new episode to an existing podcast project.
|
23
|
+
|
24
|
+
**Switch Video Focus**
|
25
|
+
Easily switch between different video projects or episodes to accommodate changing content priorities.
|
26
|
+
|
27
|
+
**Move eCamm File**
|
28
|
+
Seamlessly transfer eCamm recordings to the current focused video or podcast episode recordings subfolder.
|
29
|
+
|
30
|
+
**Project Path**
|
31
|
+
Construct and manage project paths dynamically using configurable values and existing folder name segments.
|
32
|
+
|
33
|
+
**Episode Path**
|
34
|
+
Construct and manage episode paths dynamically using configurable values and existing folder name segments.
|
35
|
+
|
36
|
+
**Recording Namer**
|
37
|
+
Dynamically generate and update video recording filenames, incorporating chapter and part sequences, chapter names, and tags, with capabilities to modify chapter sequences and tags for improved organization and content identification.
|
38
|
+
|
39
|
+
**Change Chapter Name**
|
40
|
+
Alter the name of a chapter based on its sequence in the project, facilitating better organization and identification of video content.
|
41
|
+
|
42
|
+
**Trash**
|
43
|
+
Moves suboptimal video takes to a designated 'trash' or 'archive' folder, optimizing storage and maintaining project clarity by segregating lesser-quality content.
|
44
|
+
|
45
|
+
**Trash Undo**
|
46
|
+
Retrieves video takes from the '.trash' folder and moves them back into the target project folder, allowing for reconsideration or re-evaluation of previously discarded content.
|
47
|
+
|
48
|
+
**Clean Trash**
|
49
|
+
Permanently deletes video takes from the 'trash' or 'archive' folder, freeing up storage space and ensuring project clarity.
|
50
|
+
|
51
|
+
**Open in Finder**
|
52
|
+
Quickly access video project and episode folders within the Finder, streamlining file navigation.
|
53
|
+
|
54
|
+
**Create Chapter Video**
|
55
|
+
Combine and review video chapter segments independently, facilitating content evaluation and editing.
|
56
|
+
|
57
|
+
**Text to Speech**
|
58
|
+
Transcribe spoken content to text and store transcriptions folder in multiple transcription formats.
|
59
|
+
|
60
|
+
Create a DSL using the interactor pattern for:
|
61
|
+
|
62
|
+
**Transcript Data Store**
|
63
|
+
Builds a JSON datastore of transcripts for an entire project based on existing transcript folders found within project, episode, recording, chapter and post-produced folders.
|
64
|
+
|
65
|
+
**Project Meta Data Store**
|
66
|
+
Build a JSON datastore of files for an entire project based on existing project, episode, recording, chapter and post-produced folders and infer metadata based on KEYWORDS, transcripts or other useful data.
|
67
|
+
|
68
|
+
## Future Ideas
|
69
|
+
|
70
|
+
**Web Command Interface for Video Project Management**
|
71
|
+
Introduce a streamlined, web-based interface for managing video project commands, enabling efficient control and organization of project components through simple browser interactions.
|
72
|
+
|
73
|
+
**Project Meta Report**
|
74
|
+
Generate a detailed report for a specific video project, including the episodes, chapters, recordings, a list of recording IDs (chapter sequence + part sequence), and the name for the next video recording, file sizes.
|
75
|
+
This should be extracted to an AstroJS Website or HTML template servered by a local webserver and provide viewing and navigation for all my video projects.
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
## Klue Components
|
80
|
+
|
81
|
+
Klue Component: `add_episode.klue`
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
component :add_episode do
|
85
|
+
desc "Add a new episode to an existing podcast project."
|
86
|
+
|
87
|
+
pattern "Command"
|
88
|
+
|
89
|
+
comments <<~TEXT
|
90
|
+
- Facilitates the addition of a new episode to a specific podcast project.
|
91
|
+
- Requires the project code of the podcast to ensure correct association.
|
92
|
+
- Allows setting of episode-specific details like episode code and name.
|
93
|
+
- Ensures that the episode is added only to podcast projects and not to other project types.
|
94
|
+
- Will create recording, chapter and support folders for the episode.
|
95
|
+
TEXT
|
96
|
+
|
97
|
+
method :run(:project_code, :episode_code, :episode_name)
|
98
|
+
|
99
|
+
sample :add_episode_to_podcast, <<~RUBY
|
100
|
+
# Add a new episode to existing podcast folder
|
101
|
+
add_episode.run('a21', '01', 'Episode About Something')
|
102
|
+
# Create:
|
103
|
+
# ~/video-projects/a21-ac-some-podcast/01-episode-about-something/assets
|
104
|
+
# ~/video-projects/a21-ac-some-podcast/01-episode-about-something/chapters
|
105
|
+
# ~/video-projects/a21-ac-some-podcast/01-episode-about-something/recordings
|
106
|
+
# ~/video-projects/a21-ac-some-podcast/01-episode-about-something/.trash
|
107
|
+
RUBY
|
108
|
+
end
|
109
|
+
```
|
110
|
+
|
111
|
+
Klue Component: `change_chapter_name.klue`
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
component :change_chapter_name do
|
115
|
+
desc "Alter the name of a chapter based on its sequence in the project, facilitating better organization and identification of video content."
|
116
|
+
|
117
|
+
pattern "Command"
|
118
|
+
note "This should be a method on the project"
|
119
|
+
|
120
|
+
comments <<~TEXT
|
121
|
+
- Allows the renaming of a chapter within a video project.
|
122
|
+
- Utilizes the chapter's sequence number to identify and target the specific chapter for renaming.
|
123
|
+
TEXT
|
124
|
+
|
125
|
+
method :rename_chapter(:parent, :chapter_sequence, :new_name)
|
126
|
+
|
127
|
+
<<~FILE_SYSTEM
|
128
|
+
01-a-introduction-GPTIMPROVE.mov
|
129
|
+
01-b-introduction-more-content.mov
|
130
|
+
01-c-introduction.mov
|
131
|
+
01-d-introduction-CTA.mov
|
132
|
+
02-a-overview.mov
|
133
|
+
03-a-scenario-TITLE.mov
|
134
|
+
FILE_SYSTEM
|
135
|
+
|
136
|
+
sample :change_chapter_name_in_project, <<~RUBY
|
137
|
+
# Example of changing the name of a specific chapter in a project
|
138
|
+
change_chapter_name.rename_chapter('a27', '01', 'intro')
|
139
|
+
|
140
|
+
# 01-a-intro-GPTIMPROVE.mov
|
141
|
+
# 01-b-intro.mov
|
142
|
+
# 01-c-intro.mov
|
143
|
+
# 01-d-intro-CTA.mov
|
144
|
+
RUBY
|
145
|
+
end
|
146
|
+
```
|
147
|
+
|
148
|
+
Klue Component: `create_chapter_video.klue`
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
component :create_chapter_video do
|
152
|
+
desc "Combine and all video parts for a chapter sequence and put into the chapters folder."
|
153
|
+
|
154
|
+
pattern "Command"
|
155
|
+
|
156
|
+
comments <<~TEXT
|
157
|
+
- Combines individual video segments into a single chapter video.
|
158
|
+
- Facilitates independent review and editing of each chapter.
|
159
|
+
TEXT
|
160
|
+
|
161
|
+
constructor(:parent_project)
|
162
|
+
|
163
|
+
method :run(:chapter_seq)
|
164
|
+
|
165
|
+
sample :create_chapter_video, <<~RUBY
|
166
|
+
project_path = ProjectPath.new('a27')
|
167
|
+
|
168
|
+
# Instantiate the component with the parent project
|
169
|
+
create_chapter_video = generate_chapter_video.new(project_path)
|
170
|
+
|
171
|
+
# Automatically combine all video segments for a chapter
|
172
|
+
create_chapter_video.run(1)
|
173
|
+
# Output: '~/video-projects/a27-ac-some-podcast/chapters/01-complete-chapter.mov'
|
174
|
+
RUBY
|
175
|
+
|
176
|
+
sample :create_chapter_video_for_segments, <<~RUBY
|
177
|
+
project_path = ProjectPath.new('a27')
|
178
|
+
|
179
|
+
create_chapter_video = generate_chapter_video.new(project_path)
|
180
|
+
|
181
|
+
create_chapter_video.run(1, ['01-intro-a.mov', '02-intro-b.mov'], output_file_name: '01-intro-custom.mov')
|
182
|
+
# Output: '~/video-projects/a27-ac-some-podcast/chapters/01-intro-custom.mov'
|
183
|
+
RUBY
|
184
|
+
end
|
185
|
+
```
|
186
|
+
|
187
|
+
Klue Component: `create_project.klue`
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
component :create_project do
|
191
|
+
desc "Setup a new video project for standalone YouTube video or Podcast."
|
192
|
+
|
193
|
+
pattern "Command"
|
194
|
+
|
195
|
+
comments <<~TEXT
|
196
|
+
- Allows the creation of a new project, specifying if it's for a YouTube video or a Podcast.
|
197
|
+
- For YouTube videos, the project will be single-episode based.
|
198
|
+
- For Podcasts, the project can include multiple episodes.
|
199
|
+
- Stores project-specific settings and metadata.
|
200
|
+
- Will create recording, chapter and support folders for project_type: video
|
201
|
+
TEXT
|
202
|
+
|
203
|
+
enum :project_type, %w(video podcast)
|
204
|
+
|
205
|
+
method :run(:project_type, :project_code, :channel_code, :project_name)
|
206
|
+
|
207
|
+
sample :new_video_project, <<~RUBY
|
208
|
+
# Create a new video project for AppyDave
|
209
|
+
create_project.run(:video, 'a20', 'ad', 'Some Video')
|
210
|
+
# Create:
|
211
|
+
# ~/video-projects/a20-ad-some-video
|
212
|
+
# ~/video-projects/a20-ad-some-video/.fv.json
|
213
|
+
# ~/video-projects/a20-ad-some-video/assets
|
214
|
+
# ~/video-projects/a20-ad-some-video/chapters
|
215
|
+
# ~/video-projects/a20-ad-some-video/recordings
|
216
|
+
# ~/video-projects/a20-ad-some-video/.trash
|
217
|
+
RUBY
|
218
|
+
|
219
|
+
sample :new_podcast_project, <<~RUBY
|
220
|
+
# Create a new podcast project for AppyCast
|
221
|
+
create_project.run(:podcast, 'a21', 'ac', 'Some Podcast')
|
222
|
+
# Creates folder:
|
223
|
+
# ~/video-projects/a21-ac-some-podcast
|
224
|
+
# ~/video-projects/a21-ac-some-podcast/.fv.json
|
225
|
+
RUBY
|
226
|
+
end
|
227
|
+
```
|
228
|
+
|
229
|
+
Klue Component: `empty_trash.klue`
|
230
|
+
|
231
|
+
```ruby
|
232
|
+
component :empty_trash do
|
233
|
+
desc "Permanently delete video takes from the '.trash' folder."
|
234
|
+
|
235
|
+
pattern "Command"
|
236
|
+
|
237
|
+
comments <<~TEXT
|
238
|
+
- Permanently removes all recordings from the trash folder.
|
239
|
+
- Frees up storage space by deleting unnecessary files.
|
240
|
+
- Maintains project clarity by clearing clutter.
|
241
|
+
- Ensures that only unwanted takes are deleted after a final review.
|
242
|
+
TEXT
|
243
|
+
|
244
|
+
constructor(:parent_project)
|
245
|
+
|
246
|
+
method :run
|
247
|
+
|
248
|
+
sample :permanently_delete_trash, <<~RUBY
|
249
|
+
project_path = ProjectPath.new('a27')
|
250
|
+
|
251
|
+
# Permanently deleting all contents of the trash folder
|
252
|
+
clean_trash.empty_trash
|
253
|
+
# Empties the entire .trash folder in "~/video-projects/a27-ac-categorize-mp4-CI/.trash/
|
254
|
+
RUBY
|
255
|
+
end
|
256
|
+
```
|
257
|
+
|
258
|
+
Klue Component: `episode_path.klue`
|
259
|
+
|
260
|
+
```ruby
|
261
|
+
component :episode_path do
|
262
|
+
desc "Construct episode path using project/episode code and deducing state based on existing folder name."
|
263
|
+
|
264
|
+
pattern "Adapter"
|
265
|
+
|
266
|
+
comments <<~TEXT
|
267
|
+
- Infers episode path based on episode code and existing folder name.
|
268
|
+
- Maintains state for episode code and descriptive name and keywords.
|
269
|
+
- Will use current project code if not provided.
|
270
|
+
- Path is relative to project path.
|
271
|
+
- Uses existing folder name and keywords to build internal state.
|
272
|
+
- Provides method for building absolute, relative and sub folder.
|
273
|
+
- Provides method for building a new path for rename operations.
|
274
|
+
- Provides access to associated project.
|
275
|
+
- Stores state in an internal data object.
|
276
|
+
- Designed for building folder names, not create or modify actual directories.
|
277
|
+
TEXT
|
278
|
+
|
279
|
+
accessors :episode_code, :episode_name, :keywords, :episode_path, :project
|
280
|
+
|
281
|
+
method :constructor(:episode_code, episode_name: nil, keywords: nil, project_code: nil)
|
282
|
+
method :instance(:folder)
|
283
|
+
|
284
|
+
method :change_path(episode_code: nil, episode_name: nil, keywords: nil)
|
285
|
+
|
286
|
+
# project_path.recording_path # => "~/video-projects/a27-ac-categorize-mp4-CI/recordings"
|
287
|
+
# ~/video-projects/a27-ac-categorize-mp4-CI/01-flivideo-project-kickoff-TODO/recordings
|
288
|
+
|
289
|
+
sample :create_episode_path, <<~RUBY
|
290
|
+
# Create a new episode path
|
291
|
+
episode_path = EpisodePath.new('01', episode_name: 'flivideo-project-kickoff', keywords: ['TODO'] )
|
292
|
+
episode_path.episode_path # => "~/video-projects/a27-ac-categorize-mp4-CI/01-flivideo-project-kickoff-TODO"
|
293
|
+
episode_path.episode_code # => "01"
|
294
|
+
episode_path.episode_name # => "flivideo-project-kickoff"
|
295
|
+
episode_path.keywords # => ["TODO"]
|
296
|
+
|
297
|
+
project_path = episode_path.project
|
298
|
+
project_path.project_path # => "~/video-projects/a27-ac-categorize-mp4-CI"
|
299
|
+
RUBY
|
300
|
+
|
301
|
+
sample :infer_episode_path, <<~RUBY
|
302
|
+
# Infer episode path based on episode code and existing folder
|
303
|
+
episode_path = EpisodePath.new('01')
|
304
|
+
episode_path.episode_path # => "~/video-projects/a27-ac-categorize-mp4-CI/01-flivideo-project-kickoff-TODO"
|
305
|
+
episode_path.episode_code # => "01"
|
306
|
+
episode_path.episode_name # => "flivideo-project-kickoff"
|
307
|
+
episode_path.keywords # => ["TODO"]
|
308
|
+
|
309
|
+
RUBY
|
310
|
+
|
311
|
+
sample :rename_episode_path, <<~RUBY
|
312
|
+
# Rename episode path
|
313
|
+
episode1 = EpisodePath.new('01')
|
314
|
+
episode1.episode_path # => "~/video-projects/a27-ac-categorize-mp4-CI/01-flivideo-project-kickoff-TODO"
|
315
|
+
|
316
|
+
episode2 = episode1.change_path(episode_code: '02')
|
317
|
+
episode2.episode_path # => "~/video-projects/a27-ac-categorize-mp4-CI/02-flivideo-project-kickoff-TODO"
|
318
|
+
|
319
|
+
episode3 = episode1.change_path(episode_code: '03', episode_name: 'build-gpts', keywords: [])
|
320
|
+
episode3.episode_path # => "~/video-projects/a27-ac-categorize-mp4-CI/03-build-gpts"
|
321
|
+
RUBY
|
322
|
+
|
323
|
+
sample :next_episode_code, <<~RUBY
|
324
|
+
# Get next episode code
|
325
|
+
episode_path = EpisodePath.new('01')
|
326
|
+
episode_path.next_episode_code # => "02"
|
327
|
+
RUBY
|
328
|
+
|
329
|
+
sample :folder_to_episode_path, <<~RUBY
|
330
|
+
# Convert folder to episode path
|
331
|
+
episode_path = EpisodePath.instance('~/video-projects/a27-ac-categorize-mp4-CI/01-flivideo-project-kickoff-TODO')
|
332
|
+
episode_path.episode_path # => "~/video-projects/a27-ac-categorize-mp4-CI/01-flivideo-project-kickoff-TODO"
|
333
|
+
episode_path.episode_code # => "01"
|
334
|
+
episode_path.episode_name # => "flivideo-project-kickoff"
|
335
|
+
episode_path.keywords # => ["TODO"]
|
336
|
+
RUBY
|
337
|
+
end
|
338
|
+
```
|
339
|
+
|
340
|
+
Klue Component: `global_config.klue`
|
341
|
+
|
342
|
+
```ruby
|
343
|
+
component :global_configuation do
|
344
|
+
pattern "Singleton"
|
345
|
+
|
346
|
+
desc "Access and apply global configuration settings for video asset management and state consistency."
|
347
|
+
|
348
|
+
comments <<~TEXT
|
349
|
+
Configuration file path: ~/.fli-video.json
|
350
|
+
- Automatically creates a configuration file if it does not exist.
|
351
|
+
- Responsible for reading and updating global configuration.
|
352
|
+
- Provides methods to manage folder paths and various settings.
|
353
|
+
TEXT
|
354
|
+
|
355
|
+
sample :configuration, <<~JSON
|
356
|
+
{
|
357
|
+
"folders": {
|
358
|
+
"ecamm-recordings": "~/Movies/Ecamm Live Recordings",
|
359
|
+
"project-root": "/Volumes/Expansion/Sync/tube-channels/a-cast/cast-active",
|
360
|
+
},
|
361
|
+
"settings": {
|
362
|
+
"focus-project-code": "a27",
|
363
|
+
},
|
364
|
+
}
|
365
|
+
JSON
|
366
|
+
|
367
|
+
method :set_folder(:key, :folder)
|
368
|
+
method :folder(:key)
|
369
|
+
method :set_setting(:key, :value)
|
370
|
+
method :setting(:key)
|
371
|
+
method :load
|
372
|
+
method :save
|
373
|
+
end
|
374
|
+
```
|
375
|
+
|
376
|
+
Klue Component: `move_ecamm_file.klue`
|
377
|
+
|
378
|
+
```ruby
|
379
|
+
component :move_ecamm_file do
|
380
|
+
desc "Seamlessly transfer eCamm recordings to the current focused video or podcast episode recordings subfolder."
|
381
|
+
|
382
|
+
comments <<~TEXT
|
383
|
+
- Facilitates the transfer of eCamm recording files to the appropriate project's recording subfolder.
|
384
|
+
- Automatically identifies the current focused project or episode to ensure correct file placement.
|
385
|
+
- Handles the file transfer process, maintaining file integrity and updating any necessary metadata.
|
386
|
+
- Uses global configuration to determine eCamm recording folder location.
|
387
|
+
- Uses current project configuration to determine recording subfolder location.
|
388
|
+
- Aborts the transfer process if target folder does not exist.
|
389
|
+
TEXT
|
390
|
+
|
391
|
+
method :execute(:ecamm_file_name)
|
392
|
+
|
393
|
+
sample :move_ecamm_file_to_project, <<~RUBY
|
394
|
+
# Move an eCamm recording to the currently focused project's recordings subfolder
|
395
|
+
move_ecamm_file.execute('Ecamm Live Recording on 2023-08-25 at 14.51.58.mov')
|
396
|
+
|
397
|
+
# ~/video-projects/a20-ad-some-video/recordings/Ecamm Live Recording on 2023-08-25 at 14.51.58.mov
|
398
|
+
RUBY
|
399
|
+
end
|
400
|
+
```
|
401
|
+
|
402
|
+
Klue Component: `move_to_trash.klue`
|
403
|
+
|
404
|
+
```ruby
|
405
|
+
component :move_to_trash do
|
406
|
+
desc "Move suboptimal video takes to '.trash' folder"
|
407
|
+
|
408
|
+
pattern "Command"
|
409
|
+
|
410
|
+
comments <<~TEXT
|
411
|
+
- Will trash a specific recording in a project folder.
|
412
|
+
- Will identify the last eCamm recording in a project folder if no specific recording is provided.
|
413
|
+
- Enhances project clarity and organization.
|
414
|
+
TEXT
|
415
|
+
|
416
|
+
constructure(:parent_project)
|
417
|
+
|
418
|
+
method :run(:file_name)
|
419
|
+
|
420
|
+
sample :move_video_to_trash, <<~RUBY
|
421
|
+
project_path = ProjectPath.new('a27')
|
422
|
+
|
423
|
+
command = move_to_trash.new(project_path)
|
424
|
+
|
425
|
+
# Example of moving a specific suboptimal video take to the trash folder
|
426
|
+
command.run('01-a-introduction.mov')
|
427
|
+
# => "~/video-projects/a27-ac-categorize-mp4-CI/.trash/01-a-introduction.mov"
|
428
|
+
|
429
|
+
# Example of moving the last suboptimal video take to the trash folder
|
430
|
+
command.run
|
431
|
+
# => "~/video-projects/a27-ac-categorize-mp4-CI/.trash/Ecamm Live Recording on 2023-08-25 at 14.51.58.mov
|
432
|
+
RUBY
|
433
|
+
end
|
434
|
+
```
|
435
|
+
|
436
|
+
Klue Component: `open_in_finder.klue`
|
437
|
+
|
438
|
+
```ruby
|
439
|
+
component :open_in_finder do
|
440
|
+
desc "Quickly access video project and episode folders within the Finder."
|
441
|
+
|
442
|
+
pattern "Command"
|
443
|
+
|
444
|
+
comments <<~TEXT
|
445
|
+
- Provides shortcuts to open project and episode folders in the Finder.
|
446
|
+
- Enhances efficiency in navigating to specific video project locations.
|
447
|
+
- Streamlines the process of locating and managing video files and folders.
|
448
|
+
TEXT
|
449
|
+
|
450
|
+
constructor(:parent_project)
|
451
|
+
|
452
|
+
method :run
|
453
|
+
|
454
|
+
sample :access_project_in_finder, <<~RUBY
|
455
|
+
project_path = ProjectPath.new('a27')
|
456
|
+
|
457
|
+
command = open_in_finder.new(project_path)
|
458
|
+
# Opens the folder for project 'a27' in Finder
|
459
|
+
|
460
|
+
command.run
|
461
|
+
# Opens the folder for episode '01' of project 'a27' in Finder
|
462
|
+
RUBY
|
463
|
+
end
|
464
|
+
```
|
465
|
+
|
466
|
+
Klue Component: `project_config.klue`
|
467
|
+
|
468
|
+
```ruby
|
469
|
+
component :project_configuration do
|
470
|
+
desc "Manage project / episode settings and state."
|
471
|
+
|
472
|
+
pattern "Adapter"
|
473
|
+
|
474
|
+
comments <<~TEXT
|
475
|
+
Configuration file: .fv.json
|
476
|
+
- Handles settings for single videos or the episodes in a Podcast.
|
477
|
+
- Responsible for reading and updating settings.
|
478
|
+
- Supports state management for single video, episodes, recording and chapter progression.
|
479
|
+
- This class is a reflection of the configuration file and the folders and files it manages.
|
480
|
+
|
481
|
+
Project type: video
|
482
|
+
- A single video file.
|
483
|
+
- Supports recording and chapter progression
|
484
|
+
|
485
|
+
Project type: podcast
|
486
|
+
- Multiple video files known as episodes.
|
487
|
+
- Supports recording and chapter progression for each episode.
|
488
|
+
|
489
|
+
Infers project type from the presence of the "episodes" key.
|
490
|
+
Infers project name from the name of the folder containing the configuration file.
|
491
|
+
Infers episode name from the name of the folder containing the video file.
|
492
|
+
Keeps track of prefered chapter name for each chapter sequence.
|
493
|
+
TEXT
|
494
|
+
|
495
|
+
method :load
|
496
|
+
method :save
|
497
|
+
method :resync_project_files() # refreshes the configuration based on the file system
|
498
|
+
method :current_chapter() # if type == :video
|
499
|
+
method :current_episode() # if type == :podcast
|
500
|
+
|
501
|
+
data_object :project_config do
|
502
|
+
constructor(:json)
|
503
|
+
|
504
|
+
attribute :type # video, podcast
|
505
|
+
attribute :code
|
506
|
+
attribute :chapters # if type == :video
|
507
|
+
attribute :episodes # if type == :podcast
|
508
|
+
end
|
509
|
+
|
510
|
+
data_object :episode_config do
|
511
|
+
constructor(:json)
|
512
|
+
|
513
|
+
attribute :seq # episode number store as number, but displayed as 2 digit string
|
514
|
+
attribute :chapters
|
515
|
+
attribute :current # true if this is the current episode
|
516
|
+
|
517
|
+
method :current_chapter()
|
518
|
+
end
|
519
|
+
|
520
|
+
data_object :chapter_config do
|
521
|
+
constructor(:json)
|
522
|
+
|
523
|
+
attribute :seq
|
524
|
+
attribute :preferred_name
|
525
|
+
attribute :current # true if this is the current chapter
|
526
|
+
end
|
527
|
+
|
528
|
+
sample :configuration, :for_video, <<~JSON
|
529
|
+
{
|
530
|
+
"type": "video",
|
531
|
+
"code": "e28",
|
532
|
+
"chapters": [
|
533
|
+
{
|
534
|
+
seq: 1,
|
535
|
+
preferred_name: "intro"
|
536
|
+
},
|
537
|
+
{
|
538
|
+
seq: 2,
|
539
|
+
preferred_name: "example"
|
540
|
+
},
|
541
|
+
{
|
542
|
+
seq: 3,
|
543
|
+
preferred_name: "outro",
|
544
|
+
current: true
|
545
|
+
}
|
546
|
+
]
|
547
|
+
}
|
548
|
+
JSON
|
549
|
+
|
550
|
+
sample :configuration, :for_podcast, <<~JSON
|
551
|
+
{
|
552
|
+
"type": "podcast",
|
553
|
+
"code": "e27",
|
554
|
+
"episodes": [
|
555
|
+
{
|
556
|
+
"seq": 1,
|
557
|
+
"chapters": [
|
558
|
+
{
|
559
|
+
"seq": 1,
|
560
|
+
"preferred_name": "introduction",
|
561
|
+
},
|
562
|
+
{
|
563
|
+
"seq": 2,
|
564
|
+
"preferred_name": "scenario",
|
565
|
+
"current": true
|
566
|
+
}
|
567
|
+
]
|
568
|
+
},
|
569
|
+
{
|
570
|
+
"seq": 2,
|
571
|
+
"current": true,
|
572
|
+
"chapters": [
|
573
|
+
{
|
574
|
+
"seq": 1,
|
575
|
+
"preferred_name": "introduction",
|
576
|
+
},
|
577
|
+
{
|
578
|
+
"seq": 2,
|
579
|
+
"preferred_name": "scenario",
|
580
|
+
},
|
581
|
+
{
|
582
|
+
"seq": 3,
|
583
|
+
"preferred_name": "story",
|
584
|
+
"current": true
|
585
|
+
}
|
586
|
+
]
|
587
|
+
}
|
588
|
+
]
|
589
|
+
}
|
590
|
+
JSON
|
591
|
+
end
|
592
|
+
```
|
593
|
+
|
594
|
+
Klue Component: `project_meta_data_store.klue`
|
595
|
+
|
596
|
+
```ruby
|
597
|
+
component :project_meta_data_store do
|
598
|
+
desc "Build a JSON datastore of project files with inferred metadata."
|
599
|
+
|
600
|
+
pattern "Command"
|
601
|
+
|
602
|
+
comments <<~TEXT
|
603
|
+
- Aggregates file data from project, episode, recording, chapter, and post-produced folders.
|
604
|
+
- Infers metadata from sources like KEYWORDS, transcripts, and other relevant data.
|
605
|
+
- Creates a comprehensive JSON datastore for the entire project.
|
606
|
+
- Facilitates advanced data analysis and management for the project.
|
607
|
+
- The extracted data can be used for automated post-production processes like keyword generation, B-roll prompts, chapter names, title slides, and time code markers for calls to action.
|
608
|
+
TEXT
|
609
|
+
|
610
|
+
constructor(:parent_project)
|
611
|
+
|
612
|
+
method :run
|
613
|
+
|
614
|
+
sample :build_project_metadata, <<~RUBY
|
615
|
+
project_path = ProjectPath.new('a27')
|
616
|
+
|
617
|
+
# Instantiate the component with the parent project
|
618
|
+
metadata_store = project_meta_data_store.new(project_path)
|
619
|
+
|
620
|
+
# Execute the process to aggregate files and infer metadata
|
621
|
+
metadata_store.run
|
622
|
+
# Output: '~/video-projects/a27-ac-categorize-mp4-CI/project_metadata.json'
|
623
|
+
RUBY
|
624
|
+
end
|
625
|
+
```
|
626
|
+
|
627
|
+
Klue Component: `project_path.klue`
|
628
|
+
|
629
|
+
```ruby
|
630
|
+
component :project_path do
|
631
|
+
desc "Construct project path using project code and deducing state based on existing folder name."
|
632
|
+
|
633
|
+
pattern "Adapter"
|
634
|
+
|
635
|
+
comments <<~TEXT
|
636
|
+
- Infers project path based on project code and existing folder name.
|
637
|
+
- Maintains state for project code, channel code, descriptive name, keywords and episodes.
|
638
|
+
- Uses global configuration to determine root folder.
|
639
|
+
- Uses existing folder name and keywords to build internal state.
|
640
|
+
- Provides method for building absolute, relative and sub folder.
|
641
|
+
- Provides method for building new path for rename operations.
|
642
|
+
- Provides list of associated episode paths.
|
643
|
+
- Stores state in an internal data object.
|
644
|
+
- Designed for building folder names, not create or modify actual directories.
|
645
|
+
TEXT
|
646
|
+
|
647
|
+
accessors :project_code, :channel_code, :project_name, :keywords, :project_path, :episodes
|
648
|
+
|
649
|
+
method :constructor(:project_code, channel_code: nil, project_name: nil, keywords: nil)
|
650
|
+
method :instance(:folder)
|
651
|
+
|
652
|
+
method :change_path(project_code: nil, channel_code: nil, project_name: nil, keywords: nil)
|
653
|
+
|
654
|
+
sample :create_project_path, <<~RUBY
|
655
|
+
# Create a new project path
|
656
|
+
project_path = ProjectPath.new('a27', channel_code: 'ac', project_name: 'categorize-mp4', keywords: ['CI'] )
|
657
|
+
project_path.project_path # => "~/video-projects/a27-ac-categorize-mp4-CI"
|
658
|
+
project_path.project_code # => "a27"
|
659
|
+
project_path.channel_code # => "ac"
|
660
|
+
project_path.project_name # => "categorize-mp4"
|
661
|
+
project_path.keywords # => "CI"
|
662
|
+
project_path.episodes.count # => 0
|
663
|
+
RUBY
|
664
|
+
|
665
|
+
sample :infer_project_path, <<~RUBY
|
666
|
+
# Infer project path based on project code and existing folder
|
667
|
+
project_path = ProjectPath.new('a27')
|
668
|
+
project_path.project_path # => "~/video-projects/a27-ac-categorize-mp4-CI"
|
669
|
+
project_path.project_code # => "a27"
|
670
|
+
project_path.channel_code # => "ac"
|
671
|
+
project_path.project_name # => "categorize-mp4"
|
672
|
+
project_path.keywords # => "CI"
|
673
|
+
project_path.episodes.count # => 2
|
674
|
+
RUBY
|
675
|
+
|
676
|
+
sample :rename_project_path, <<~RUBY
|
677
|
+
# Rename project path
|
678
|
+
project_path = ProjectPath.new('a27')
|
679
|
+
|
680
|
+
path1 = project_path.change_path(project_code: 'a28')
|
681
|
+
path1.project_path # => "~/video-projects/a28-ac-categorize-mp4-CI"
|
682
|
+
path2 = project_path.change_path(channel_code: 'ad', project_name: 'categorize-mp4-for-appydave')
|
683
|
+
path2.project_path # => "~/video-projects/a27-ad-categorize-mp4-for-appydave-CI"
|
684
|
+
path3 = project_path.change_path(keywords: [])
|
685
|
+
path3.project_path # => "~/video-projects/a27-ac-categorize-mp4"
|
686
|
+
RUBY
|
687
|
+
|
688
|
+
sample :next_project_code, <<~RUBY
|
689
|
+
# Get next project code
|
690
|
+
project_path = ProjectPath.new('a27')
|
691
|
+
project_path.next_project_code # => "a28"
|
692
|
+
|
693
|
+
project_path = ProjectPath.new('a99')
|
694
|
+
project_path.next_project_code # => "b00"
|
695
|
+
RUBY
|
696
|
+
|
697
|
+
sample :folder_to_project_path, <<~RUBY
|
698
|
+
# Convert folder to project path
|
699
|
+
project_path = ProjectPath.instance('~/video-projects/a27-ac-categorize-mp4-CI')
|
700
|
+
project_path.project_path # => "~/video-projects/a27-ac-categorize-mp4-CI"
|
701
|
+
project_path.project_code # => "a27"
|
702
|
+
project_path.channel_code # => "ac"
|
703
|
+
project_path.project_name # => "categorize-mp4"
|
704
|
+
project_path.keywords # => "CI"
|
705
|
+
RUBY
|
706
|
+
end
|
707
|
+
```
|
708
|
+
|
709
|
+
Klue Component: `recording_file_watcher.klue`
|
710
|
+
|
711
|
+
```ruby
|
712
|
+
component :filewatch_processor do
|
713
|
+
desc "Automate file event responses, directing new recordings to current project folders."
|
714
|
+
|
715
|
+
pattern "Observer"
|
716
|
+
|
717
|
+
comments <<~TEXT
|
718
|
+
- Monitors new eCamm recordings file events.
|
719
|
+
- Automates the process of moving new recordings to specified project folders.
|
720
|
+
- Enhances content management by ensuring recordings are organized efficiently.
|
721
|
+
- Configurable to respond to different types of file events and target folders.
|
722
|
+
TEXT
|
723
|
+
|
724
|
+
method :watch(:folder_path, :event_type)
|
725
|
+
|
726
|
+
# Will move the file to current project's recordings folder
|
727
|
+
method :move_file
|
728
|
+
|
729
|
+
sample :automate_recording_organization, <<~RUBY
|
730
|
+
config = GlobalConfig.instance
|
731
|
+
|
732
|
+
# Watch a specific folder for new and existing recordings
|
733
|
+
filewatch_processor.watch(config.folders['ecamm-recordings'], '*.mov', :moved_file)
|
734
|
+
|
735
|
+
# Example usage
|
736
|
+
# When a new file is detected in Ecamm Live Recordings, it is automatically moved to the current project's recordings folder.
|
737
|
+
filewatch_processor.move_file
|
738
|
+
RUBY
|
739
|
+
end
|
740
|
+
```
|
741
|
+
|
742
|
+
Klue Component: `recording_filename.klue`
|
743
|
+
|
744
|
+
```ruby
|
745
|
+
component :recording_filename do
|
746
|
+
desc "Calculate the next video recording file name based on chapter sequence, part number, chapter name, and tags if available."
|
747
|
+
|
748
|
+
pattern "Adapter"
|
749
|
+
|
750
|
+
comments <<~TEXT
|
751
|
+
- File name construction for new and existing video recordings.
|
752
|
+
- Utilizes the chapter and part sequence for systematic naming.
|
753
|
+
- Incorporates the chapter name for descriptive clarity.
|
754
|
+
- Has support for tags in the file name to aid content identification and post-processing workflows.
|
755
|
+
- Set episode & project via the episode if recording belongs to an episode
|
756
|
+
- Set project if recording belongs to a project
|
757
|
+
- Parent returns episode || project
|
758
|
+
TEXT
|
759
|
+
|
760
|
+
accessors :chapter_seq, :part_seq, :chapter_name, :tags, :filename, :episode, :project, :parent
|
761
|
+
|
762
|
+
method :constructor(:chapter_seq, :part_seq, :chapter_name, tags: [], parent: nil)
|
763
|
+
method :instance(:full_path)
|
764
|
+
|
765
|
+
# Use the current chapter sequence if not provided
|
766
|
+
# Part sequence will increment based on the previous part letter in the chapter if not provided
|
767
|
+
# Chapter name will defaults to previous recording chapter name if not provided
|
768
|
+
method :next_filename(:previous_filename, chapter_name: nil, tags: [], chapter_seq: nil, part_seq: nil)
|
769
|
+
method :update_chapter_sequence(:current_chapter_seq, :new_chapter_seq)
|
770
|
+
method :resequence_chapters(:starting_chapter_seq)
|
771
|
+
method :update_tags(:new_tags)
|
772
|
+
|
773
|
+
sample :create_recording_filename, <<~RUBY
|
774
|
+
project_path = ProjectPath.new('a27')
|
775
|
+
project_path.project_path # => "~/video-projects/a27-ac-categorize-mp4-CI"
|
776
|
+
|
777
|
+
# Generate a filename for a new video recording
|
778
|
+
filename1 = RecordingFilename.new(1, 'a' 'introduction', tags: [], parent: project_path)
|
779
|
+
filename1.filename # => "01-a-introduction.mov"
|
780
|
+
filename1.chapter_seq # => 1
|
781
|
+
filename1.part_seq # => "a"
|
782
|
+
filename1.chapter_name # => "introduction"
|
783
|
+
filename1.tags # => []
|
784
|
+
filename1.full_path # => "~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov"
|
785
|
+
RUBY
|
786
|
+
|
787
|
+
sample :next_recording_filename, <<~RUBY
|
788
|
+
filename1 = "~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov"
|
789
|
+
|
790
|
+
project = ProjectConfig.new('a27')
|
791
|
+
|
792
|
+
# Class method to generate a filename for a new video recording
|
793
|
+
filename2 = RecordingFilename.next_filename(filename1, chapter_name: 'introduction-more-content', tags: ['GPTIMPROVE'])
|
794
|
+
|
795
|
+
# Fluent method to generate a filename for a new video recording
|
796
|
+
filename3 = filename2.next_filename(chapter_name: 'introduction')
|
797
|
+
filename4 = filename3.next_filename(tags: ['CTA'])
|
798
|
+
|
799
|
+
project.next_chapter('overview')
|
800
|
+
|
801
|
+
filename5 = RecordingFilename.next_filename(project.last_file)
|
802
|
+
|
803
|
+
project.next_chapter('scenario')
|
804
|
+
|
805
|
+
filename6 = RecordingFilename.next_filename(project.last_file, tags: ['TITLE'])
|
806
|
+
|
807
|
+
filename1.filename # => "01-a-introduction-GPTIMPROVE.mov" # Send transcription to GPT Bot for improvement
|
808
|
+
filename2.filename # => "01-b-introduction-more-content.mov"
|
809
|
+
filename3.filename # => "01-c-introduction.mov"
|
810
|
+
filename4.filename # => "01-d-introduction-CTA.mov" # Instruction for video editor to add a CTA
|
811
|
+
filename5.filename # => "02-a-overview.mov"
|
812
|
+
filename6.filename # => "03-a-scenario-TITLE.mov" # Instruction for video editor to add a title slide
|
813
|
+
RUBY
|
814
|
+
|
815
|
+
sample :file_to_recording_filename, <<~RUBY
|
816
|
+
# Convert absolute file to recording filename
|
817
|
+
filename = RecordingFilename.instance('~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov')
|
818
|
+
|
819
|
+
filename.filename # => "01-a-introduction.mov"
|
820
|
+
filename.chapter_seq # => 1
|
821
|
+
filename.part_seq # => "a"
|
822
|
+
filename.chapter_name # => "introduction"
|
823
|
+
filename.tags # => []
|
824
|
+
filename.full_path # => "~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov"
|
825
|
+
RUBY
|
826
|
+
|
827
|
+
sample :rename_recording_filename, <<~RUBY
|
828
|
+
filename = RecordingFilename.instance('~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov')
|
829
|
+
filename.filename # => "01-a-introduction.mov"
|
830
|
+
|
831
|
+
filename.change_filename(chapter_name: 'introduction-trim-23s', tags: ['GPTDALE3'])
|
832
|
+
filename.filename # => "01-a-introduction-trim-23s-GPTDALE3.mov"
|
833
|
+
RUBY
|
834
|
+
|
835
|
+
sample :update_chapter_sequence, <<~RUBY
|
836
|
+
project_path = ProjectPath.new('a27')
|
837
|
+
|
838
|
+
# Update chapter sequence in a project
|
839
|
+
filename = RecordingFilename.new(2, 'b', 'overview', parent: project_path)
|
840
|
+
filename.update_chapter_sequence(2, 3)
|
841
|
+
filename.filename # => "03-b-overview.mov"
|
842
|
+
RUBY
|
843
|
+
|
844
|
+
sample :resequence_chapters, <<~RUBY
|
845
|
+
# Resequence chapters starting from a given sequence
|
846
|
+
filename.resequence_chapters(2)
|
847
|
+
# Adjusts chapter sequence of all subsequent chapters starting from '02'
|
848
|
+
RUBY
|
849
|
+
|
850
|
+
sample :update_tags, <<~RUBY
|
851
|
+
# Update tags for a recording
|
852
|
+
filename = RecordingFilename.new(1, 'a', 'introduction', tags: ['OLD_TAG'], parent: project_path)
|
853
|
+
filename.update_tags(['NEW_TAG'])
|
854
|
+
filename.filename # => "01-a-introduction-NEW_TAG.mov"
|
855
|
+
RUBY
|
856
|
+
end
|
857
|
+
```
|
858
|
+
|
859
|
+
Klue Component: `restore_from_trash.klue`
|
860
|
+
|
861
|
+
```ruby
|
862
|
+
component :restore_from_trash do
|
863
|
+
desc "Retrieve video takes from '.trash' folder and move them back to the project folder."
|
864
|
+
|
865
|
+
pattern "Command"
|
866
|
+
|
867
|
+
comments <<~TEXT
|
868
|
+
- Restores a specific recording from the trash to the project folder.
|
869
|
+
- If no specific recording is provided, restores the most recently trashed recording.
|
870
|
+
- Facilitates reconsideration or re-evaluation of previously discarded content.
|
871
|
+
TEXT
|
872
|
+
|
873
|
+
constructor(:parent_project)
|
874
|
+
|
875
|
+
method :run(:file_name)
|
876
|
+
|
877
|
+
sample :restore_from_trash, <<~RUBY
|
878
|
+
project_path = ProjectPath.new('a27')
|
879
|
+
|
880
|
+
command = undo_trash.new(project_path)
|
881
|
+
|
882
|
+
# Example of restoring a specific recording from the trash folder
|
883
|
+
command.run('01-a-introduction.mov')
|
884
|
+
# => "~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov"
|
885
|
+
|
886
|
+
# Example of restoring the most recently trashed recording
|
887
|
+
command.run
|
888
|
+
# => "~/video-projects/a27-ac-categorize-mp4-CI/Ecamm Live Recording on 2023-08-25 at 14.51.58.mov"
|
889
|
+
RUBY
|
890
|
+
end
|
891
|
+
```
|
892
|
+
|
893
|
+
Klue Component: `switch_focus.klue`
|
894
|
+
|
895
|
+
```ruby
|
896
|
+
component :change_focus do
|
897
|
+
desc "Easily switch between different video projects or episodes to accommodate changing content priorities."
|
898
|
+
|
899
|
+
pattern "Interactor"
|
900
|
+
|
901
|
+
comments <<~TEXT
|
902
|
+
- Allows switching the focus to a different video project or a specific episode within a podcast.
|
903
|
+
- Video recordings belong to a specific project or episode and this interaction ensures that the correct project or episode is in focus.
|
904
|
+
- Ensures seamless transition and updates the working context to the selected project or episode.
|
905
|
+
- Maintains state consistency across switches using the global configuration.
|
906
|
+
TEXT
|
907
|
+
|
908
|
+
method :run(:project_code, episode_code: nil)
|
909
|
+
|
910
|
+
sample :switch_focus_to_video_project, <<~RUBY
|
911
|
+
# Switch focus to a different video project
|
912
|
+
change_focus.run('a20')
|
913
|
+
RUBY
|
914
|
+
|
915
|
+
sample :switch_focus_to_podcast_episode, <<~RUBY
|
916
|
+
# Switch focus to a specific episode within a podcast project
|
917
|
+
change_focus.run('a21', '02')
|
918
|
+
RUBY
|
919
|
+
end
|
920
|
+
```
|
921
|
+
|
922
|
+
Klue Component: `text_to_speech.klue`
|
923
|
+
|
924
|
+
```ruby
|
925
|
+
component :text_to_speech do
|
926
|
+
desc "Transcribe spoken content to text and store in multiple transcription formats."
|
927
|
+
|
928
|
+
pattern "Command"
|
929
|
+
|
930
|
+
comments <<~TEXT
|
931
|
+
- Transcribes audio content from videos into text.
|
932
|
+
- Supports storing transcriptions in various formats for accessibility and further processing.
|
933
|
+
- Uses the transcript folder under the recording, chapter or post-production folder and stores the transcriptions in a subfolder called 'transcript'.
|
934
|
+
TEXT
|
935
|
+
|
936
|
+
constructor(:parent_project)
|
937
|
+
|
938
|
+
method :run(:recording_file, output_formats:)
|
939
|
+
|
940
|
+
sample :transcribe_audio_to_text, <<~RUBY
|
941
|
+
project_path = ProjectPath.new('a27')
|
942
|
+
|
943
|
+
# ~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov
|
944
|
+
# Instantiate the component with the parent project
|
945
|
+
tts = text_to_speech.new(project_path)
|
946
|
+
|
947
|
+
# Execute the transcription against
|
948
|
+
tts.run('01-introduction.mov', output_formats: ['txt', 'srt', 'vtt', 'json', 'tsv'])
|
949
|
+
|
950
|
+
# Transcribes '01-introduction.mov' and stores the transcriptions in the specified formats
|
951
|
+
# Output: Transcriptions saved in '~/video-projects/a27-ac-categorize-mp4-CI/recordings/transcript/01-introduction.txt|srt|vtt|json|tsv'
|
952
|
+
RUBY
|
953
|
+
end
|
954
|
+
```
|
955
|
+
|
956
|
+
Klue Component: `transcript_data_store.klue`
|
957
|
+
|
958
|
+
```ruby
|
959
|
+
component :transcript_data_store do
|
960
|
+
desc "Build a JSON datastore of transcripts for an entire project."
|
961
|
+
|
962
|
+
pattern "Command"
|
963
|
+
|
964
|
+
comments <<~TEXT
|
965
|
+
- Aggregates transcripts from various project levels into a single JSON datastore.
|
966
|
+
- Scans project, episode, recording, chapter, and post-produced folders for existing transcripts.
|
967
|
+
- Facilitates easy access and management of transcript data across the entire project.
|
968
|
+
- Enhances data retrieval and analysis capabilities for the project's transcripts.
|
969
|
+
- Stores data in a JSON file called 'transcripts.json' in the project folder.
|
970
|
+
TEXT
|
971
|
+
|
972
|
+
constructor(:parent_project)
|
973
|
+
|
974
|
+
method :run
|
975
|
+
|
976
|
+
sample :build_transcript_datastore, <<~RUBY
|
977
|
+
project_path = ProjectPath.new('a27')
|
978
|
+
|
979
|
+
# Instantiate the component with the parent project
|
980
|
+
transcript_store = transcript_data_store.new(project_path)
|
981
|
+
|
982
|
+
# Execute the process to aggregate and store transcript data
|
983
|
+
transcript_store.run
|
984
|
+
# Output: '~/video-projects/a27-ac-categorize-mp4-CI/project_transcripts.json'
|
985
|
+
RUBY
|
986
|
+
end
|
987
|
+
```
|
988
|
+
|