fli_video 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/.builders/klues/add_episode.klue +25 -0
  3. data/.builders/klues/change_chapter_name.klue +32 -0
  4. data/.builders/klues/create_chapter_video.klue +34 -0
  5. data/.builders/klues/create_project.klue +37 -0
  6. data/.builders/klues/empty_trash.klue +24 -0
  7. data/.builders/klues/episode_path.klue +77 -0
  8. data/.builders/klues/global_config.klue +31 -0
  9. data/.builders/klues/move_ecamm_file.klue +21 -0
  10. data/.builders/klues/move_to_trash.klue +29 -0
  11. data/.builders/klues/open_in_finder.klue +25 -0
  12. data/.builders/klues/project_config.klue +123 -0
  13. data/.builders/klues/project_meta_data_store.klue +28 -0
  14. data/.builders/klues/project_path.klue +77 -0
  15. data/.builders/klues/recording_file_watcher.klue +28 -0
  16. data/.builders/klues/recording_filename.klue +112 -0
  17. data/.builders/klues/restore_from_trash.klue +29 -0
  18. data/.builders/klues/switch_focus.klue +24 -0
  19. data/.builders/klues/text_to_speech.klue +29 -0
  20. data/.builders/klues/transcript_data_store.klue +28 -0
  21. data/.rubocop.yml +2 -0
  22. data/CHANGELOG.md +18 -0
  23. data/README.md +13 -20
  24. data/bin/fli_video +6 -0
  25. data/docs/feature-list.md +75 -0
  26. data/docs/generated/application-structure.json +57 -0
  27. data/docs/generated/features-and-components.md +987 -0
  28. data/docs/generated/technical-design-and-features.md +420 -0
  29. data/docs/technical-specifications.md +347 -0
  30. data/fli.rb +138 -0
  31. data/lib/fli_video/cli.rb +30 -0
  32. data/lib/fli_video/version.rb +1 -1
  33. data/package-lock.json +2 -2
  34. data/package.json +1 -1
  35. data/scripts/01-get-structure.rb +84 -0
  36. data/scripts/02-get-features-and-components.rb +38 -0
  37. data/scripts/03-get-technical-design-and-features.rb +27 -0
  38. metadata +32 -3
  39. data/README-features.md +0 -36
@@ -0,0 +1,112 @@
1
+ component :recording_filename do
2
+ desc "Calculate the next video recording file name based on chapter sequence, part number, chapter name, and tags if available."
3
+
4
+ pattern "Adapter"
5
+
6
+ comments <<~TEXT
7
+ - File name construction for new and existing video recordings.
8
+ - Utilizes the chapter and part sequence for systematic naming.
9
+ - Incorporates the chapter name for descriptive clarity.
10
+ - Has support for tags in the file name to aid content identification and post-processing workflows.
11
+ - Set episode & project via the episode if recording belongs to an episode
12
+ - Set project if recording belongs to a project
13
+ - Parent returns episode || project
14
+ TEXT
15
+
16
+ accessors :chapter_seq, :part_seq, :chapter_name, :tags, :filename, :episode, :project, :parent
17
+
18
+ method :constructor(:chapter_seq, :part_seq, :chapter_name, tags: [], parent: nil)
19
+ method :instance(:full_path)
20
+
21
+ # Use the current chapter sequence if not provided
22
+ # Part sequence will increment based on the previous part letter in the chapter if not provided
23
+ # Chapter name will defaults to previous recording chapter name if not provided
24
+ method :next_filename(:previous_filename, chapter_name: nil, tags: [], chapter_seq: nil, part_seq: nil)
25
+ method :update_chapter_sequence(:current_chapter_seq, :new_chapter_seq)
26
+ method :resequence_chapters(:starting_chapter_seq)
27
+ method :update_tags(:new_tags)
28
+
29
+ sample :create_recording_filename, <<~RUBY
30
+ project_path = ProjectPath.new('a27')
31
+ project_path.project_path # => "~/video-projects/a27-ac-categorize-mp4-CI"
32
+
33
+ # Generate a filename for a new video recording
34
+ filename1 = RecordingFilename.new(1, 'a' 'introduction', tags: [], parent: project_path)
35
+ filename1.filename # => "01-a-introduction.mov"
36
+ filename1.chapter_seq # => 1
37
+ filename1.part_seq # => "a"
38
+ filename1.chapter_name # => "introduction"
39
+ filename1.tags # => []
40
+ filename1.full_path # => "~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov"
41
+ RUBY
42
+
43
+ sample :next_recording_filename, <<~RUBY
44
+ filename1 = "~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov"
45
+
46
+ project = ProjectConfig.new('a27')
47
+
48
+ # Class method to generate a filename for a new video recording
49
+ filename2 = RecordingFilename.next_filename(filename1, chapter_name: 'introduction-more-content', tags: ['GPTIMPROVE'])
50
+
51
+ # Fluent method to generate a filename for a new video recording
52
+ filename3 = filename2.next_filename(chapter_name: 'introduction')
53
+ filename4 = filename3.next_filename(tags: ['CTA'])
54
+
55
+ project.next_chapter('overview')
56
+
57
+ filename5 = RecordingFilename.next_filename(project.last_file)
58
+
59
+ project.next_chapter('scenario')
60
+
61
+ filename6 = RecordingFilename.next_filename(project.last_file, tags: ['TITLE'])
62
+
63
+ filename1.filename # => "01-a-introduction-GPTIMPROVE.mov" # Send transcription to GPT Bot for improvement
64
+ filename2.filename # => "01-b-introduction-more-content.mov"
65
+ filename3.filename # => "01-c-introduction.mov"
66
+ filename4.filename # => "01-d-introduction-CTA.mov" # Instruction for video editor to add a CTA
67
+ filename5.filename # => "02-a-overview.mov"
68
+ filename6.filename # => "03-a-scenario-TITLE.mov" # Instruction for video editor to add a title slide
69
+ RUBY
70
+
71
+ sample :file_to_recording_filename, <<~RUBY
72
+ # Convert absolute file to recording filename
73
+ filename = RecordingFilename.instance('~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov')
74
+
75
+ filename.filename # => "01-a-introduction.mov"
76
+ filename.chapter_seq # => 1
77
+ filename.part_seq # => "a"
78
+ filename.chapter_name # => "introduction"
79
+ filename.tags # => []
80
+ filename.full_path # => "~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov"
81
+ RUBY
82
+
83
+ sample :rename_recording_filename, <<~RUBY
84
+ filename = RecordingFilename.instance('~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov')
85
+ filename.filename # => "01-a-introduction.mov"
86
+
87
+ filename.change_filename(chapter_name: 'introduction-trim-23s', tags: ['GPTDALE3'])
88
+ filename.filename # => "01-a-introduction-trim-23s-GPTDALE3.mov"
89
+ RUBY
90
+
91
+ sample :update_chapter_sequence, <<~RUBY
92
+ project_path = ProjectPath.new('a27')
93
+
94
+ # Update chapter sequence in a project
95
+ filename = RecordingFilename.new(2, 'b', 'overview', parent: project_path)
96
+ filename.update_chapter_sequence(2, 3)
97
+ filename.filename # => "03-b-overview.mov"
98
+ RUBY
99
+
100
+ sample :resequence_chapters, <<~RUBY
101
+ # Resequence chapters starting from a given sequence
102
+ filename.resequence_chapters(2)
103
+ # Adjusts chapter sequence of all subsequent chapters starting from '02'
104
+ RUBY
105
+
106
+ sample :update_tags, <<~RUBY
107
+ # Update tags for a recording
108
+ filename = RecordingFilename.new(1, 'a', 'introduction', tags: ['OLD_TAG'], parent: project_path)
109
+ filename.update_tags(['NEW_TAG'])
110
+ filename.filename # => "01-a-introduction-NEW_TAG.mov"
111
+ RUBY
112
+ end
@@ -0,0 +1,29 @@
1
+ component :restore_from_trash do
2
+ desc "Retrieve video takes from '.trash' folder and move them back to the project folder."
3
+
4
+ pattern "Command"
5
+
6
+ comments <<~TEXT
7
+ - Restores a specific recording from the trash to the project folder.
8
+ - If no specific recording is provided, restores the most recently trashed recording.
9
+ - Facilitates reconsideration or re-evaluation of previously discarded content.
10
+ TEXT
11
+
12
+ constructor(:parent_project)
13
+
14
+ method :run(:file_name)
15
+
16
+ sample :restore_from_trash, <<~RUBY
17
+ project_path = ProjectPath.new('a27')
18
+
19
+ command = undo_trash.new(project_path)
20
+
21
+ # Example of restoring a specific recording from the trash folder
22
+ command.run('01-a-introduction.mov')
23
+ # => "~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov"
24
+
25
+ # Example of restoring the most recently trashed recording
26
+ command.run
27
+ # => "~/video-projects/a27-ac-categorize-mp4-CI/Ecamm Live Recording on 2023-08-25 at 14.51.58.mov"
28
+ RUBY
29
+ end
@@ -0,0 +1,24 @@
1
+ component :change_focus do
2
+ desc "Easily switch between different video projects or episodes to accommodate changing content priorities."
3
+
4
+ pattern "Interactor"
5
+
6
+ comments <<~TEXT
7
+ - Allows switching the focus to a different video project or a specific episode within a podcast.
8
+ - Video recordings belong to a specific project or episode and this interaction ensures that the correct project or episode is in focus.
9
+ - Ensures seamless transition and updates the working context to the selected project or episode.
10
+ - Maintains state consistency across switches using the global configuration.
11
+ TEXT
12
+
13
+ method :run(:project_code, episode_code: nil)
14
+
15
+ sample :switch_focus_to_video_project, <<~RUBY
16
+ # Switch focus to a different video project
17
+ change_focus.run('a20')
18
+ RUBY
19
+
20
+ sample :switch_focus_to_podcast_episode, <<~RUBY
21
+ # Switch focus to a specific episode within a podcast project
22
+ change_focus.run('a21', '02')
23
+ RUBY
24
+ end
@@ -0,0 +1,29 @@
1
+ component :text_to_speech do
2
+ desc "Transcribe spoken content to text and store in multiple transcription formats."
3
+
4
+ pattern "Command"
5
+
6
+ comments <<~TEXT
7
+ - Transcribes audio content from videos into text.
8
+ - Supports storing transcriptions in various formats for accessibility and further processing.
9
+ - Uses the transcript folder under the recording, chapter or post-production folder and stores the transcriptions in a subfolder called 'transcript'.
10
+ TEXT
11
+
12
+ constructor(:parent_project)
13
+
14
+ method :run(:recording_file, output_formats:)
15
+
16
+ sample :transcribe_audio_to_text, <<~RUBY
17
+ project_path = ProjectPath.new('a27')
18
+
19
+ # ~/video-projects/a27-ac-categorize-mp4-CI/01-a-introduction.mov
20
+ # Instantiate the component with the parent project
21
+ tts = text_to_speech.new(project_path)
22
+
23
+ # Execute the transcription against
24
+ tts.run('01-introduction.mov', output_formats: ['txt', 'srt', 'vtt', 'json', 'tsv'])
25
+
26
+ # Transcribes '01-introduction.mov' and stores the transcriptions in the specified formats
27
+ # Output: Transcriptions saved in '~/video-projects/a27-ac-categorize-mp4-CI/recordings/transcript/01-introduction.txt|srt|vtt|json|tsv'
28
+ RUBY
29
+ end
@@ -0,0 +1,28 @@
1
+ component :transcript_data_store do
2
+ desc "Build a JSON datastore of transcripts for an entire project."
3
+
4
+ pattern "Command"
5
+
6
+ comments <<~TEXT
7
+ - Aggregates transcripts from various project levels into a single JSON datastore.
8
+ - Scans project, episode, recording, chapter, and post-produced folders for existing transcripts.
9
+ - Facilitates easy access and management of transcript data across the entire project.
10
+ - Enhances data retrieval and analysis capabilities for the project's transcripts.
11
+ - Stores data in a JSON file called 'transcripts.json' in the project folder.
12
+ TEXT
13
+
14
+ constructor(:parent_project)
15
+
16
+ method :run
17
+
18
+ sample :build_transcript_datastore, <<~RUBY
19
+ project_path = ProjectPath.new('a27')
20
+
21
+ # Instantiate the component with the parent project
22
+ transcript_store = transcript_data_store.new(project_path)
23
+
24
+ # Execute the process to aggregate and store transcript data
25
+ transcript_store.run
26
+ # Output: '~/video-projects/a27-ac-categorize-mp4-CI/project_transcripts.json'
27
+ RUBY
28
+ end
data/.rubocop.yml CHANGED
@@ -14,6 +14,8 @@ AllCops:
14
14
  Exclude:
15
15
  - ".builders/**/*"
16
16
  - "spec/samples/**/*"
17
+ - "scripts/**/*"
18
+ - "fli.rb"
17
19
 
18
20
  Metrics/BlockLength:
19
21
  Exclude:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,21 @@
1
+ ## [0.0.2](https://github.com/klueless-io/fli_video/compare/v0.0.1...v0.0.2) (2023-12-19)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * downgrade sem ver ([34c7f77](https://github.com/klueless-io/fli_video/commit/34c7f77bf52b899cbc36e202b71ea9530177e9a7))
7
+ * naming issue ([b573d05](https://github.com/klueless-io/fli_video/commit/b573d056e044c8054ef1f98fc8219041efac86ab))
8
+ * package json issue ([efc9435](https://github.com/klueless-io/fli_video/commit/efc9435d829585db1fc27878f134f5f8b802f5a0))
9
+ * ruby 2.7 ([303d59f](https://github.com/klueless-io/fli_video/commit/303d59f49fd7cbc09e2ac0b2c89ba8538d3dd37b))
10
+ * testing semver1 ([f71b294](https://github.com/klueless-io/fli_video/commit/f71b2944c6bffa8c85859b247dced28f9cc61cdd))
11
+ * testing semver2 ([f0ea217](https://github.com/klueless-io/fli_video/commit/f0ea217416783452db4a0efee0df37ac64391bb1))
12
+ * testing semver3 ([c28ffa8](https://github.com/klueless-io/fli_video/commit/c28ffa8b428216807046acec74935e6fee6f710a))
13
+ * testing semver4 ([c1e260d](https://github.com/klueless-io/fli_video/commit/c1e260d069e88f72b4505dd52050305fd6de64cd))
14
+ * version fixed for semver ([c65bf64](https://github.com/klueless-io/fli_video/commit/c65bf64335b040ca96e6aab495f7b73cfeda4f8d))
15
+ * version fixed for semver ([484225f](https://github.com/klueless-io/fli_video/commit/484225ff32be5dc21a6e9c7231f73c59f6753ada))
16
+ * version fixed for semver ([1011cd9](https://github.com/klueless-io/fli_video/commit/1011cd90daf6631078b22be47c8a37265ab8b6f2))
17
+ * version normalization ([e50f6ac](https://github.com/klueless-io/fli_video/commit/e50f6acf3500ee1b5cc80cb57ea24823a017d905))
18
+
1
19
  ## [Unreleased]
2
20
 
3
21
  ## [0.1.0] - 2023-12-19
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  > FliVideo - Video Asset Management for Content Creators
4
4
 
5
+ GPT Link: https://chat.openai.com/c/895a1bf9-8134-4688-8805-b8047af5f3f0
6
+
5
7
  ## Installation
6
8
 
7
9
  Add this line to your application's Gemfile:
@@ -22,13 +24,21 @@ Or install it yourself as:
22
24
  gem install fli_video
23
25
  ```
24
26
 
25
- ## Stories
27
+ ## Documentation
28
+
29
+ ### Technical Design Document
30
+
31
+ The main design document is located here: [Technical Specification](docs/technical-specifications.md)
32
+
33
+ ### Feature List
34
+
35
+ List of features that are planned for this project: [Feature List](docs/feature-list.md)
26
36
 
27
37
  ### Main Story
28
38
 
29
39
  As a content creator, I want to create quality videos quickly, so that I can build my YouTube influence
30
40
 
31
- See all [stories](./STORIES.md)
41
+ See all [stories](./stories.md)
32
42
 
33
43
 
34
44
  ## Usage
@@ -36,7 +46,6 @@ See all [stories](./STORIES.md)
36
46
  See all [usage examples](./USAGE.md)
37
47
 
38
48
 
39
-
40
49
  ## Development
41
50
 
42
51
  Checkout the repo
@@ -49,25 +58,9 @@ After checking out the repo, run `bin/setup` to install dependencies. Then, run
49
58
 
50
59
  You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
60
 
52
- ```bash
53
- bin/console
54
-
55
- Aaa::Bbb::Program.execute()
56
- # => ""
57
- ```
58
-
59
- `fli_video` is setup with Guard, run `guard`, this will watch development file changes and run tests automatically, if successful, it will then run rubocop for style quality.
60
-
61
- To release a new version, update the version number in `version.rb`, build the gem and push the `.gem` file to [rubygems.org](https://rubygems.org).
62
-
63
- ```bash
64
- rake publish
65
- rake clean
66
- ```
67
-
68
61
  ## Git helpers used by this project
69
62
 
70
- Add the follow helpers to your `alias` file
63
+ Add the follow helpers to your `alias` file so that you can use Semantic Commits and have them automatically pushed to GitHub and have the CI/CD pipeline run.
71
64
 
72
65
  ```bash
73
66
  function kcommit()
data/bin/fli_video ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative '../lib/fli_video/cli'
5
+
6
+ FliVideo::CLI.start(ARGV)
@@ -0,0 +1,75 @@
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.
@@ -0,0 +1,57 @@
1
+ [
2
+ {
3
+ "name": "spec",
4
+ "type": "directory",
5
+ "children": [
6
+ {
7
+ "name": "spec_helper.rb",
8
+ "type": "file",
9
+ "content": "# frozen_string_literal: true\n\nrequire 'pry'\nrequire 'bundler/setup'\nrequire 'simplecov'\n\nSimpleCov.start\n\nrequire 'fli_video'\n\nRSpec.configure do |config|\n # Enable flags like --only-failures and --next-failure\n config.example_status_persistence_file_path = '.rspec_status'\n config.filter_run_when_matching :focus\n\n # Disable RSpec exposing methods globally on `Module` and `main`\n config.disable_monkey_patching!\n\n config.expect_with :rspec do |c|\n c.syntax = :expect\n end\nend\n"
10
+ },
11
+ {
12
+ "name": "fli_video_spec.rb",
13
+ "type": "file",
14
+ "content": "# frozen_string_literal: true\n\nRSpec.describe FliVideo do\n it 'has a version number' do\n expect(FliVideo::VERSION).not_to be_nil\n end\nend\n"
15
+ }
16
+ ]
17
+ },
18
+ {
19
+ "name": "README.md",
20
+ "type": "file"
21
+ },
22
+ {
23
+ "name": "readme-current-project-setup.md",
24
+ "type": "file"
25
+ },
26
+ {
27
+ "name": "lib",
28
+ "type": "directory",
29
+ "children": [
30
+ {
31
+ "name": "fli_video",
32
+ "type": "directory",
33
+ "children": [
34
+ {
35
+ "name": "cli.rb",
36
+ "type": "file",
37
+ "content": "# frozen_string_literal: true\n\nrequire_relative '../fli_video'\n\nmodule FliVideo\n class CLI\n def self.start(args)\n new(args).execute\n end\n\n def initialize(args)\n @args = args\n end\n\n def execute\n if @args.empty?\n puts \"FliVideo CLI - No command provided\"\n return\n end\n\n case @args.first\n when 'version'\n puts \"FliVideo version #{FliVideo::VERSION}\"\n else\n puts \"Unknown command: #{@args.first}\"\n end\n end\n end\nend\n"
38
+ },
39
+ {
40
+ "name": "version.rb",
41
+ "type": "file",
42
+ "content": "# frozen_string_literal: true\n\nmodule FliVideo\n VERSION = '0.0.2'\nend\n"
43
+ }
44
+ ]
45
+ },
46
+ {
47
+ "name": "fli_video.rb",
48
+ "type": "file",
49
+ "content": "# frozen_string_literal: true\n\nrequire_relative 'fli_video/version'\n\nmodule FliVideo\n class Error < StandardError; end\n # Your code goes here...\nend\n"
50
+ }
51
+ ]
52
+ },
53
+ {
54
+ "name": "Gemfile",
55
+ "type": "file"
56
+ }
57
+ ]