multimedia_paradise 1.1.344 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (218) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +99 -77
  3. data/bin/audio_player +1 -1
  4. data/bin/extract_images_from_this_video_file +1 -1
  5. data/bin/loop_this_video +1 -1
  6. data/bin/merge_avi_files +1 -1
  7. data/bin/merge_mp3 +1 -1
  8. data/bin/mp3_to_opus +1 -1
  9. data/bin/mpg_to_mp4 +1 -1
  10. data/bin/multimedia_paradise +1 -1
  11. data/bin/to_aiff +2 -5
  12. data/bin/to_flac +7 -0
  13. data/bin/to_mp3 +8 -0
  14. data/bin/to_mp4 +1 -1
  15. data/bin/to_ogg +7 -0
  16. data/bin/verbose_analyse_this_mp3_file_for_id3_tags +1 -1
  17. data/bin/video_codec +1 -1
  18. data/bin/video_thumbnail +1 -1
  19. data/bin/video_to_images +1 -1
  20. data/doc/README.gen +88 -51
  21. data/doc/{CHANGELOG.md → changelog/changelog.md} +8 -6
  22. data/doc/{LINKS.md → links/links.md} +2 -2
  23. data/doc/{MOTIVATION_FOR_THIS_PROJECT.md → motivation_for_the_multimedia_paradise_project/motivation_for_the_multimedia_paradise_project.md} +5 -5
  24. data/doc/todo/todo_for_the_multimedia_paradise_project.md +79 -93
  25. data/lib/multimedia_paradise/actions/actions.rb +224 -0
  26. data/lib/multimedia_paradise/audio/audio_player/audio_player.rb +61 -64
  27. data/lib/multimedia_paradise/audio/audio_tag_reader/audio_tag_reader.rb +17 -8
  28. data/lib/multimedia_paradise/audio/base.rb +0 -5
  29. data/lib/multimedia_paradise/audio/compress.rb +8 -5
  30. data/lib/multimedia_paradise/audio/create_m3u_playlist.rb +7 -11
  31. data/lib/multimedia_paradise/audio/extract_audio/constants.rb +0 -37
  32. data/lib/multimedia_paradise/audio/extract_audio/extract_audio.rb +90 -68
  33. data/lib/multimedia_paradise/audio/file_duration/file_duration.rb +134 -80
  34. data/lib/multimedia_paradise/audio/genres/boogie.rb +1 -6
  35. data/lib/multimedia_paradise/audio/genres/concerts.rb +1 -6
  36. data/lib/multimedia_paradise/audio/genres/constants.rb +1 -1
  37. data/lib/multimedia_paradise/audio/genres/eurodance.rb +1 -6
  38. data/lib/multimedia_paradise/audio/genres/genre.rb +36 -33
  39. data/lib/multimedia_paradise/audio/genres/hip_hop.rb +1 -6
  40. data/lib/multimedia_paradise/audio/genres/italian_songs.rb +1 -6
  41. data/lib/multimedia_paradise/audio/genres/the_1980s.rb +1 -6
  42. data/lib/multimedia_paradise/audio/genres/trance.rb +4 -7
  43. data/lib/multimedia_paradise/audio/lyrics_fetcher.rb +27 -22
  44. data/lib/multimedia_paradise/audio/merge_audio_files.rb +18 -11
  45. data/lib/multimedia_paradise/audio/modify_year_of_audio_file.rb +23 -11
  46. data/lib/multimedia_paradise/audio/n_audio_songs.rb +3 -2
  47. data/lib/multimedia_paradise/audio/play_all_audio_files.rb +41 -16
  48. data/lib/multimedia_paradise/audio/playlist/playlist.rb +163 -123
  49. data/lib/multimedia_paradise/audio/remove_audio.rb +11 -6
  50. data/lib/multimedia_paradise/audio/remove_last_second.rb +2 -3
  51. data/lib/multimedia_paradise/audio/report_missing_id.rb +22 -12
  52. data/lib/multimedia_paradise/audio/streamripper/streamripper_wrapper.rb +7 -5
  53. data/lib/multimedia_paradise/audio/to_mp3.rb +7 -5
  54. data/lib/multimedia_paradise/audio/to_ogg.rb +3 -1
  55. data/lib/multimedia_paradise/audio/wav_to_mp3.rb +5 -5
  56. data/lib/multimedia_paradise/base/base.rb +854 -15
  57. data/lib/multimedia_paradise/base/colours.rb +28 -31
  58. data/lib/multimedia_paradise/base/{commandline_arguments.rb → commandline_arguments_module/commandline_arguments_module.rb} +12 -9
  59. data/lib/multimedia_paradise/colours/colours.rb +4 -1
  60. data/lib/multimedia_paradise/commandline/{menu.rb → commandline.rb} +19 -16
  61. data/lib/multimedia_paradise/constants/constants.rb +504 -14
  62. data/lib/multimedia_paradise/constants/web_constants.rb +2 -4
  63. data/lib/multimedia_paradise/gui/gui_base.rb +2 -2
  64. data/lib/multimedia_paradise/gui/libui/lyrics/lyrics.rb +1 -1
  65. data/lib/multimedia_paradise/gui/libui/simple_play_widget/simple_play_widget.rb +1 -1
  66. data/lib/multimedia_paradise/gui/libui/video_player/video_player.rb +1 -1
  67. data/lib/multimedia_paradise/gui/libui/youtube_channels/youtube_channels.rb +1 -1
  68. data/lib/multimedia_paradise/gui/shared_code/multimedia_converter/multimedia_converter_module.rb +0 -478
  69. data/lib/multimedia_paradise/gui/shared_code/playlist/playlist_module.rb +94 -41
  70. data/lib/multimedia_paradise/gui/shared_code/simple_play_widget/simple_play_widget_module.rb +0 -257
  71. data/lib/multimedia_paradise/gui/universal_widgets/change_metadata_widget/change_metadata_widget.rb +2 -2
  72. data/lib/multimedia_paradise/gui/universal_widgets/information_about_a_mp3_file/information_about_a_mp3_file.rb +1 -1
  73. data/lib/multimedia_paradise/gui/universal_widgets/lyrics/lyrics.rb +1 -1
  74. data/lib/multimedia_paradise/gui/universal_widgets/multimedia_converter/multimedia_converter.rb +589 -0
  75. data/lib/multimedia_paradise/gui/universal_widgets/playlist/playlist.rb +197 -0
  76. data/lib/multimedia_paradise/gui/universal_widgets/radio/radio.rb +1 -1
  77. data/lib/multimedia_paradise/gui/{gtk2 → universal_widgets}/simple_play_widget/README.md +1 -1
  78. data/lib/multimedia_paradise/gui/universal_widgets/simple_play_widget/simple_play_widget.rb +404 -0
  79. data/lib/multimedia_paradise/gui/universal_widgets/tag_mp3_files/tag_mp3_files.rb +3 -6
  80. data/lib/multimedia_paradise/java/Playlist.class +0 -0
  81. data/lib/multimedia_paradise/java/Playlist.java +198 -0
  82. data/lib/multimedia_paradise/multimedia/analyse_multimedia_file.rb +21 -19
  83. data/lib/multimedia_paradise/multimedia/avisynth/avisynth_code.avs +441 -442
  84. data/lib/multimedia_paradise/multimedia/base.rb +0 -18
  85. data/lib/multimedia_paradise/multimedia/chord.rb +1 -1
  86. data/lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb +7 -5
  87. data/lib/multimedia_paradise/multimedia/cut_multimedia/evaluate_from_this_file.rb +2 -2
  88. data/lib/multimedia_paradise/multimedia/interactive_shell.rb +22 -3
  89. data/lib/multimedia_paradise/multimedia/merge_multimedia.rb +4 -3
  90. data/lib/multimedia_paradise/multimedia/play_from_this_list.rb +4 -27
  91. data/lib/multimedia_paradise/multimedia/{read_meta_tags.rb → read_meta_tags/read_meta_tags.rb} +14 -19
  92. data/lib/multimedia_paradise/multimedia/start_length_duration.rb +3 -3
  93. data/lib/multimedia_paradise/project/project.rb +8 -4
  94. data/lib/multimedia_paradise/requires/require_the_multimedia_paradise_project.rb +5 -5
  95. data/lib/multimedia_paradise/requires/require_toplevel_methods_files.rb +1 -1
  96. data/lib/multimedia_paradise/sinatra/app.rb +3 -3
  97. data/lib/multimedia_paradise/statistics/README.md +6 -5
  98. data/lib/multimedia_paradise/statistics/video.rb +34 -14
  99. data/lib/multimedia_paradise/{misc → time}/long_format_to_milliseconds_converter.rb +4 -2
  100. data/lib/multimedia_paradise/{misc → time}/milliseconds_to_long_format_converter.rb +2 -2
  101. data/lib/multimedia_paradise/toplevel_methods/audio_related_code.rb +138 -0
  102. data/lib/multimedia_paradise/toplevel_methods/chop_into_segments_of_n_seconds_size.rb +2 -2
  103. data/lib/multimedia_paradise/{conversions → toplevel_methods}/conversions.rb +140 -48
  104. data/lib/multimedia_paradise/toplevel_methods/copy_and_merge_this_video_n_times.rb +5 -5
  105. data/lib/multimedia_paradise/toplevel_methods/create_video_from_this_audio.rb +7 -6
  106. data/lib/multimedia_paradise/toplevel_methods/cut_from_to.rb +2 -2
  107. data/lib/multimedia_paradise/toplevel_methods/denoise.rb +2 -2
  108. data/lib/multimedia_paradise/toplevel_methods/deshake.rb +3 -6
  109. data/lib/multimedia_paradise/toplevel_methods/{output_directory.rb → directory_related_code.rb} +38 -1
  110. data/lib/multimedia_paradise/toplevel_methods/encode_this_video.rb +8 -4
  111. data/lib/multimedia_paradise/toplevel_methods/esystem.rb +43 -4
  112. data/lib/multimedia_paradise/{ffmpeg → toplevel_methods}/ffmpeg.rb +200 -193
  113. data/lib/multimedia_paradise/toplevel_methods/{files_and_directories.rb → files_related_code.rb} +19 -56
  114. data/lib/multimedia_paradise/toplevel_methods/flip_and_rotate.rb +3 -3
  115. data/lib/multimedia_paradise/toplevel_methods/is_audio_file_is_video_file_is_image_file_is_multimedia_file.rb +115 -0
  116. data/lib/multimedia_paradise/toplevel_methods/is_on_roebe.rb +1 -1
  117. data/lib/multimedia_paradise/toplevel_methods/{merge_multimedia_file.rb → merge.rb} +98 -4
  118. data/lib/multimedia_paradise/toplevel_methods/opn.rb +5 -4
  119. data/lib/multimedia_paradise/toplevel_methods/player_in_use.rb +14 -7
  120. data/lib/multimedia_paradise/toplevel_methods/query_the_audio_codec_of_this_file.rb +4 -3
  121. data/lib/multimedia_paradise/toplevel_methods/radio.rb +1 -3
  122. data/lib/multimedia_paradise/toplevel_methods/return_all_video_files.rb +4 -4
  123. data/lib/multimedia_paradise/toplevel_methods/return_path_to_random_simpsons_video_file.rb +1 -1
  124. data/lib/multimedia_paradise/toplevel_methods/return_random_video_file_from_the_video_collection.rb +9 -7
  125. data/lib/multimedia_paradise/toplevel_methods/scale_video.rb +3 -4
  126. data/lib/multimedia_paradise/toplevel_methods/set_title_of.rb +6 -6
  127. data/lib/multimedia_paradise/{help/help.rb → toplevel_methods/show_help.rb} +14 -8
  128. data/lib/multimedia_paradise/toplevel_methods/slow_down_this_video_file.rb +2 -3
  129. data/lib/multimedia_paradise/toplevel_methods/start_screencast.rb +3 -2
  130. data/lib/multimedia_paradise/toplevel_methods/{misc.rb → toplevel_methods.rb} +485 -527
  131. data/lib/multimedia_paradise/toplevel_methods/total_duration.rb +4 -3
  132. data/lib/multimedia_paradise/toplevel_methods/use_lame_codec.rb +1 -2
  133. data/lib/multimedia_paradise/toplevel_methods/video_dataset.rb +1 -1
  134. data/lib/multimedia_paradise/version/version.rb +2 -2
  135. data/lib/multimedia_paradise/video/all_videos.rb +12 -19
  136. data/lib/multimedia_paradise/video/check_numbers.rb +76 -32
  137. data/lib/multimedia_paradise/video/columbo/columbo.rb +36 -14
  138. data/lib/multimedia_paradise/video/guess_video_name.rb +2 -10
  139. data/lib/multimedia_paradise/video/mike_hammer/mike_hammer.rb +2 -2
  140. data/lib/multimedia_paradise/video/missing_video_files/missing_video_files.rb +1 -9
  141. data/lib/multimedia_paradise/video/movie_searcher.rb +2 -10
  142. data/lib/multimedia_paradise/video/mplayer_wrapper.rb +1 -9
  143. data/lib/multimedia_paradise/video/random_video.rb +1 -2
  144. data/lib/multimedia_paradise/video/registered_video_file.rb +2 -10
  145. data/lib/multimedia_paradise/video/report_local_videos.rb +1 -9
  146. data/lib/multimedia_paradise/video/simpsons.rb +2 -10
  147. data/lib/multimedia_paradise/video/smart_animals/smart_animals.rb +10 -8
  148. data/lib/multimedia_paradise/video/speed_up_video.rb +28 -10
  149. data/lib/multimedia_paradise/video/store_available_video_files.rb +49 -33
  150. data/lib/multimedia_paradise/video/the_simpsons/README.md +0 -0
  151. data/lib/multimedia_paradise/video/the_simpsons/good_the_simpsons_episodes.rb +8 -8
  152. data/lib/multimedia_paradise/video/the_simpsons/the_simpsons.rb +14 -10
  153. data/lib/multimedia_paradise/video/video_information.rb +55 -49
  154. data/lib/multimedia_paradise/{configuration → yaml/configuration}/play_zoomed.yml +0 -0
  155. data/lib/multimedia_paradise/yaml/{playlist.yml → playlist/playlist.yml} +14 -15
  156. data/lib/multimedia_paradise/yaml/video/video.yml +1 -1
  157. data/lib/multimedia_paradise/yaml/video_collection/video_collection.yml +34 -32
  158. data/lib/multimedia_paradise/yaml/youtube/alltagsgeschichte/alltagsgeschichte.yml +61 -11
  159. data/lib/multimedia_paradise/yaml/youtube/songs/songs.yml +5 -3
  160. data/multimedia_paradise.gemspec +1 -1
  161. data/test/testing_audio_player.rb +3 -3
  162. data/test/testing_file_duration.rb +5 -5
  163. metadata +45 -76
  164. data/lib/multimedia_paradise/audio/file_duration/constants.rb +0 -53
  165. data/lib/multimedia_paradise/audio/waveform/class.rb +0 -341
  166. data/lib/multimedia_paradise/audio/waveform/constants.rb +0 -38
  167. data/lib/multimedia_paradise/audio/waveform/log.rb +0 -101
  168. data/lib/multimedia_paradise/base/constants.rb +0 -19
  169. data/lib/multimedia_paradise/base/encoding.rb +0 -31
  170. data/lib/multimedia_paradise/base/misc.rb +0 -665
  171. data/lib/multimedia_paradise/base/namespace.rb +0 -36
  172. data/lib/multimedia_paradise/base/time.rb +0 -25
  173. data/lib/multimedia_paradise/constants/conversions.rb +0 -62
  174. data/lib/multimedia_paradise/constants/directory_constants.rb +0 -139
  175. data/lib/multimedia_paradise/constants/encodings.rb +0 -26
  176. data/lib/multimedia_paradise/constants/file_constants.rb +0 -176
  177. data/lib/multimedia_paradise/constants/misc.rb +0 -80
  178. data/lib/multimedia_paradise/constants/my_video_directory.rb +0 -30
  179. data/lib/multimedia_paradise/constants/namespace.rb +0 -14
  180. data/lib/multimedia_paradise/constants/newline.rb +0 -14
  181. data/lib/multimedia_paradise/constants/video_filetypes.rb +0 -27
  182. data/lib/multimedia_paradise/conversions/README.md +0 -2
  183. data/lib/multimedia_paradise/ffmpeg/README.md +0 -2
  184. data/lib/multimedia_paradise/gui/gtk2/multimedia_converter/multimedia_converter.rb +0 -33
  185. data/lib/multimedia_paradise/gui/gtk2/notebook.rb +0 -144
  186. data/lib/multimedia_paradise/gui/gtk2/play_video_from_my_collection/play_video_from_my_collection.rb +0 -43
  187. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/simple_play_widget.rb +0 -40
  188. data/lib/multimedia_paradise/gui/gtk2/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +0 -42
  189. data/lib/multimedia_paradise/gui/gtk2/youtube_downloader/youtube_downloader.rb +0 -32
  190. data/lib/multimedia_paradise/gui/gtk3/lyrics/lyrics.rb +0 -0
  191. data/lib/multimedia_paradise/gui/gtk3/multimedia_converter/multimedia_converter.rb +0 -34
  192. data/lib/multimedia_paradise/gui/gtk3/playlist/playlist.rb +0 -34
  193. data/lib/multimedia_paradise/gui/gtk3/simple_play_widget/simple_play_widget.rb +0 -38
  194. data/lib/multimedia_paradise/toplevel_methods/analyze_audio_stream.rb +0 -31
  195. data/lib/multimedia_paradise/toplevel_methods/codecs.rb +0 -50
  196. data/lib/multimedia_paradise/toplevel_methods/copy_file.rb +0 -18
  197. data/lib/multimedia_paradise/toplevel_methods/delay_audio.rb +0 -31
  198. data/lib/multimedia_paradise/toplevel_methods/ensure_that_the_output_directory_exists.rb +0 -27
  199. data/lib/multimedia_paradise/toplevel_methods/has_audio.rb +0 -48
  200. data/lib/multimedia_paradise/toplevel_methods/increase_volume_of_this_audio_file.rb +0 -61
  201. data/lib/multimedia_paradise/toplevel_methods/is_a_multimedia_file.rb +0 -27
  202. data/lib/multimedia_paradise/toplevel_methods/is_audio_file.rb +0 -27
  203. data/lib/multimedia_paradise/toplevel_methods/is_image_file.rb +0 -31
  204. data/lib/multimedia_paradise/toplevel_methods/is_video_file.rb +0 -62
  205. data/lib/multimedia_paradise/toplevel_methods/merge_these_videos.rb +0 -106
  206. data/lib/multimedia_paradise/toplevel_methods/run_sys_command.rb +0 -30
  207. data/lib/multimedia_paradise/toplevel_methods/to_flac.rb +0 -30
  208. data/lib/multimedia_paradise/toplevel_methods/to_mp4.rb +0 -24
  209. /data/doc/{MergingVideoLectures.md → merging_video_lectures/merging_video_lectures.md} +0 -0
  210. /data/doc/{Readme_for_the_cut_audio_component.md → readme_for_the_cut_audio_component/Readme_for_the_cut_audio_component.md} +0 -0
  211. /data/lib/multimedia_paradise/yaml/{audio_formats.yml → audio_formats/audio_formats.yml} +0 -0
  212. /data/lib/multimedia_paradise/yaml/{image_formats.yml → image_formats/image_formats.yml} +0 -0
  213. /data/lib/multimedia_paradise/yaml/{lyrics.yml → lyrics/lyrics.yml} +0 -0
  214. /data/lib/multimedia_paradise/yaml/{music_genres.yml → music_genres/music_genres.yml} +0 -0
  215. /data/lib/multimedia_paradise/yaml/{song_tags.yml → song_tags/song_tags.yml} +0 -0
  216. /data/lib/multimedia_paradise/yaml/{use_this_video_player.yml → use_this_video_player/use_this_video_player.yml} +0 -0
  217. /data/lib/multimedia_paradise/yaml/{video_encoding_settings.yml → video_encoding_settings/video_encoding_settings.yml} +0 -0
  218. /data/lib/multimedia_paradise/yaml/{video_filter_aliases.yml → video_filter_aliases/video_filter_aliases.yml} +0 -0
@@ -2,7 +2,7 @@
2
2
  # Encoding: UTF-8
3
3
  # frozen_string_literal: true
4
4
  # =========================================================================== #
5
- # require 'multimedia_paradise/toplevel_methods/misc.rb'
5
+ # require 'multimedia_paradise/toplevel_methods/toplevel_methods.rb'
6
6
  # MultimediaParadise.extract_images_from_this_video_file
7
7
  # MultimediaParadise.bitrate_of_this_song
8
8
  # MultimediaParadise.verbose_analyse_this_mp3_file_for_id3_tags
@@ -11,16 +11,9 @@
11
11
  # =========================================================================== #
12
12
  module MultimediaParadise
13
13
 
14
- require 'multimedia_paradise/constants/misc.rb'
14
+ require 'multimedia_paradise/constants/constants.rb'
15
15
  require 'multimedia_paradise/toplevel_methods/esystem.rb'
16
- require 'multimedia_paradise/ffmpeg/ffmpeg.rb'
17
-
18
- # ========================================================================= #
19
- # === MultimediaParadise.return_all_video_files_from_the_current_directory
20
- # ========================================================================= #
21
- def self.return_all_video_files_from_the_current_directory
22
- Dir['**'].select {|entry| is_a_video_file?(entry) }
23
- end
16
+ require 'multimedia_paradise/toplevel_methods/ffmpeg.rb'
24
17
 
25
18
  # ========================================================================= #
26
19
  # === MultimediaParadise.automatically_create_a_thumbnail_for_this_video
@@ -50,37 +43,23 @@ module MultimediaParadise
50
43
  end; self.instance_eval { alias thumbnail automatically_create_a_thumbnail_for_this_video } # === MultimediaParadise.thumbnail
51
44
 
52
45
  # ========================================================================= #
53
- # === MultimediaParadise.mpg_to_mp4
46
+ # === MultimediaParadise.open_yaml_file
54
47
  #
55
- # This is an opinionated method.
48
+ # This will open my video collection.
49
+ # ========================================================================= #
50
+ def self.open_yaml_file(
51
+ i = FILE_VIDEO_COLLECTION
52
+ )
53
+ esystem "bluefish #{i}"
54
+ end
55
+
56
+ # ========================================================================= #
57
+ # === MultimediaParadise.return_all_video_files_from_the_current_directory
56
58
  #
57
- # You have to pass the filename to this method, in order to convert
58
- # the .mpg files into .mp4 files.
59
+ # This method will obtain all video-files from the current directory.
59
60
  # ========================================================================= #
60
- def self.mpg_to_mp4(*i)
61
- # ======================================================================= #
62
- # Going with crf 26 - that seems to be a bit better than 25, actually.
63
- # ======================================================================= #
64
- crf_value_to_use = '26' # 25-28 should suffice; lower value means higher quality and larger file size.
65
- result = []
66
- i.flatten.each {|this_file|
67
- this_file = File.absolute_path(this_file)
68
- output_file = File.dirname(this_file)+'/'+
69
- 'output_'+
70
- File.basename(this_file).
71
- delete_suffix(
72
- File.extname(this_file)
73
- )+'.mp4'
74
- _ = 'ffmpeg -i '+this_file.to_s+' -c:v libx265 -c:a libmp3lame '\
75
- '-crf '+crf_value_to_use.to_s+' '\
76
- '-preset:v veryslow '+
77
- output_file
78
- e
79
- esystem _
80
- e
81
- result << File.absolute_path(output_file)
82
- }
83
- result # We must return the output files here.
61
+ def self.return_all_video_files_from_the_current_directory
62
+ Dir['**'].select {|entry| is_a_video_file?(entry) }
84
63
  end
85
64
 
86
65
  # ========================================================================= #
@@ -135,178 +114,392 @@ module MultimediaParadise
135
114
  self.instance_eval { alias video_codec? return_video_codec_of_this_file } # === MultimediaParadise.video_codec?
136
115
 
137
116
  # ========================================================================= #
138
- # === MultimediaParadise.return_the_mpeg_layer_from_this_mp3_file
117
+ # === MultimediaParadise.set_the_aspect_ratio_of_this_video
139
118
  #
140
- # This method will make use of the binary called "mpg123".
141
- # ========================================================================= #
142
- def self.return_the_mpeg_layer_from_this_mp3_file(i)
143
- cmd = "mpg123 -t #{i} 2>&1"
144
- result = `#{cmd}`
145
- splitted = result.split("\n")
146
- selected = splitted.select {|line|
147
- line.start_with? 'MPEG ' # Obtain the MPEG layer here.
148
- }.uniq
149
- result = selected.first # Pick the first result here.
150
- # ======================================================================= #
151
- # We may have to clean up that result a little bit still.
152
- # ======================================================================= #
153
- if result and result.include?(' ') and result.include?('III')
154
- result = result[0 .. (result.index('III')+2)]
155
- end
156
- return result
157
- end
158
-
159
- # ========================================================================= #
160
- # === MultimediaParadise.loop_this_video
119
+ # This method will set the aspect-ratio of a given video file, via
120
+ # ffmpeg. The commandline-flag for this is called -aspect.
161
121
  #
162
- # This method can be used to loop a video, via ffmpeg.
122
+ # Original example:
163
123
  #
164
- # A commandline variant for this would look as follows:
124
+ # ffmpeg -i foo.mp4 -aspect 16:9 bar.mp4
165
125
  #
166
- # ffmpeg -stream_loop 3 -i Tata.webm -c copy output.webm
126
+ # Example for the MultimediaParadise namespace:
127
+ #
128
+ # MultimediaParadise.set_the_aspect_ratio_of_this_video('foo.mpg')
167
129
  #
168
130
  # ========================================================================= #
169
- def self.loop_this_video(this_video = 'foobar.webm', n_times = '5x')
170
- result = []
171
- [this_video].flatten.compact.each {|work_on_this_video_file|
172
- n_times = n_times.to_s.delete('x').sub(/ times/,'')
173
- output_file = "output_#{work_on_this_video_file}"
174
- result << output_file
175
- cmd = "ffmpeg -stream_loop #{n_times} -i #{work_on_this_video_file} -c copy #{output_file}"
176
- esystem cmd
177
- }
178
- return result
131
+ def self.set_the_aspect_ratio_of_this_video(
132
+ this_video, use_this_aspect_ratio = '16:9'
133
+ )
134
+ extension_to_use = File.extname(this_video)
135
+ cmd_to_use = 'ffmpeg -i '+this_video+' -aspect '+
136
+ use_this_aspect_ratio+' output_'+
137
+ this_video.sub(/#{extension_to_use}$/,'')+extension_to_use
138
+ e
139
+ e cmd_to_use
140
+ e
141
+ system cmd_to_use
179
142
  end
180
143
 
181
144
  # ========================================================================= #
182
- # === MultimediaParadise.bin_dir?
145
+ # === MultimediaParadise.load_yaml
183
146
  # ========================================================================= #
184
- def self.bin_dir?
185
- RbConfig::CONFIG['bindir'].to_s+'/' # Ensure trailing '/'.
186
- end; self.instance_eval { alias bindir? bin_dir? } # === MultimediaParadise.bindir?
147
+ def self.load_yaml(i)
148
+ YAML.load_file(i)
149
+ end
187
150
 
188
151
  # ========================================================================= #
189
- # === MultimediaParadise.copy_bin_directory
190
- #
191
- # This method can be used to copy the content of the bin/ directory
192
- # onto the current working directory.
193
- #
194
- # Usage example from within ruby code:
152
+ # === MultimediaParadise.flip_video_to_the_left
195
153
  #
196
- # require 'multimedia_paradise'; MultimediaParadise.copy_bin_directory
154
+ # This toplevel-method can be used to flip a video to the left,
155
+ # that is, to rotate it by -90 degrees.
197
156
  #
157
+ # It will tap into ffmpeg for this task.
198
158
  # ========================================================================= #
199
- def self.copy_bin_directory
200
- file_installed_binaries = "#{MultimediaParadise.project_base_directory?}"\
201
- "yaml/internal/installed_binaries.yml"
202
- mkdir('bin/')
203
- cd('bin/')
204
- if File.exist? file_installed_binaries
205
- e 'Making use of the file '+sfile(file_installed_binaries)+'.'
206
- install_these_binaries = YAML.load_file(file_installed_binaries)
207
- installation_directory = `gem env`.split("\n").select {|line| # Check for INSTALLATION DIRECTORY: /root/.gem
208
- line.include? 'INSTALLATION DIRECTORY:'
209
- }.first.
210
- scan(/INSTALLATION DIRECTORY: (.+)$/).flatten.first
211
- install_these_binaries.each {|entry|
212
- target = installation_directory+'/bin/'+entry
213
- if File.exist? target
214
- e "Copying the file #{target} into the current working "\
215
- "directory next."
216
- copy_file(target, Dir.pwd)
217
- else
218
- # ================================================================= #
219
- # Since as of January 2023 first try the bin_dir, before giving up.
220
- # ================================================================= #
221
- target = MultimediaParadise.bin_dir?+File.basename(entry)
222
- if File.exist? target
223
- e "Copying the file #{target} into the current working "\
224
- "directory next."
225
- copy_file(target, Dir.pwd)
226
- else
227
- no_file_exists_at(target)
228
- end
229
- end
230
- }
231
- end
159
+ def self.flip_video_to_the_left(i)
160
+ ffmpeg_flip_video_to_the_left(i)
232
161
  end
233
162
 
234
163
  # ========================================================================= #
235
- # === MultimediaParadise.to_gif
236
- #
237
- # This method can be used to quickly turn an .avi file or a .mp4
238
- # file into an animated .gif.
239
- #
240
- # The quality is pretty low, so this is not ideal, but if you
241
- # have a use case for animated .gif files then this is one
242
- # way to do so.
243
- #
244
- # Usage example:
245
- #
246
- # MultimediaParadise.to_gif('foobar.mp4')
164
+ # === MultimediaParadise.flip_video_to_the_right
247
165
  #
166
+ # This toplevel-method can be used to flip a video to the right,
167
+ # that is, to rotate it by +90 degrees.
248
168
  # ========================================================================= #
249
- def self.to_gif(i)
250
- [i].flatten.compact.each {|this_video_file|
251
- _ = File.basename(this_video_file).
252
- delete_suffix(
253
- File.extname(this_video_file)
254
- )
255
- name_of_the_output_gif_file = "output_#{_}.gif"
256
- cmd = "ffmpeg -i #{this_video_file} -pix_fmt rgb8 #{name_of_the_output_gif_file}" # Or use 0rgb.
257
- esystem(cmd)
258
- return name_of_the_output_gif_file
259
- }
169
+ def self.flip_video_to_the_right(i)
170
+ ffmpeg_flip_video_to_the_right(i)
260
171
  end
261
-
172
+
262
173
  # ========================================================================= #
263
- # === MultimediaParadise.create_noise_profile
264
- #
265
- # Note that this method depends on the external program called "sox".
266
- #
267
- # Usage example:
268
- #
269
- # MultimediaParadise.create_noise_profile('foobar.mp3')
174
+ # === MultimediaParadise.compress_this_ogg_file
270
175
  #
176
+ # This method will use a sampling rate of 22050 Hz. This should be
177
+ # perfectly adequate for speech-related audio, but I also found it
178
+ # to work well when compressing a tetris.ogg file (for the game
179
+ # tetris).
271
180
  # ========================================================================= #
272
- def self.create_noise_profile(
273
- of_this_mp3_file
181
+ def self.compress_this_ogg_file(i = 'foobar.ogg')
182
+ _ = 'ffmpeg -i '+entry+' '\
183
+ '-c:a libvorbis -ab 32k '\
184
+ '-ar 22050'\
185
+ ' OUTPUT_'+i
186
+ e
187
+ esystem _
188
+ e
189
+ end
190
+
191
+ # ========================================================================= #
192
+ # === MultimediaParadise.try_to_rename_kde_konsole_tab
193
+ # ========================================================================= #
194
+ def self.try_to_rename_kde_konsole_tab(
195
+ new_title = '_',
196
+ try_to_rename_the_kde_konsole_tab = TRY_TO_RENAME_THE_KDE_KONSOLE_TAB
274
197
  )
275
- array_results = []
276
- [of_this_mp3_file].flatten.compact.each {|work_on_this_mp3_file|
277
- work_on_this_mp3_file = File.absolute_path(work_on_this_mp3_file)
278
- filename_without_extension = work_on_this_mp3_file.delete_suffix('.mp3')
279
- this_profile_file_is_to_be_created = "noise_profile_based_on_#{File.basename(filename_without_extension)}"
280
- if File.exist?(this_profile_file_is_to_be_created) # Always remove old profiles.
281
- File.delete(this_profile_file_is_to_be_created)
198
+ if try_to_rename_the_kde_konsole_tab
199
+ begin
200
+ require 'roebe/requires/require_kde_konsole.rb'
201
+ rescue LoadError
202
+ e 'roebe/requires/require_kde_konsole.rb is not available'
282
203
  end
283
- cmd_to_run = "sox #{work_on_this_mp3_file} -n noiseprof #{this_profile_file_is_to_be_created}.profile"
284
- e cmd_to_run
285
- `#{cmd_to_run}`
286
- array_results << this_profile_file_is_to_be_created
287
- }
288
- return array_results
289
- end
204
+ if Object.const_defined?(:Roebe) and
205
+ Roebe.respond_to?(:rename_konsole)
206
+ Roebe.rename_konsole(new_title)
207
+ end
208
+ end
209
+ end; self.instance_eval { alias rename_kde_konsole try_to_rename_kde_konsole_tab } # === MultimediaParadise.rename_kde_konsole
210
+ self.instance_eval { alias do_rename_konsole try_to_rename_kde_konsole_tab } # === MultimediaParadise.do_rename_konsole
211
+ self.instance_eval { alias rename_kde_konsole_tab try_to_rename_kde_konsole_tab } # === MultimediaParadise.rename_kde_konsole_tab
290
212
 
291
213
  # ========================================================================= #
292
- # === MultimediaParadise.shrink_quality_of_these_mp3_files
214
+ # === MultimediaParadise.crop_this_video
293
215
  #
294
- # This method can be used to batch-shrink several .mp3 files in one go.
216
+ # This method can be used to crop a particular video file, via
217
+ # ffmpeg.
295
218
  #
296
- # Usage example:
219
+ # The raw ffmpeg-command would go like something like this:
297
220
  #
298
- # MultimediaParadise.shrink_quality_of_these_mp3_files(Dir['*.mp3'])
221
+ # ffmpeg -i input.mp4 -filter:v "crop=out_w:out_h:x:y" output.mp4
222
+ #
223
+ # These variables are:
224
+ #
225
+ # → out_w is the width of the output rectangle
226
+ # → out_h is the height of the output rectangle
227
+ # → x and y specify the top left corner of the output rectangle
228
+ # → output.mp4 is the output file
299
229
  #
300
230
  # ========================================================================= #
301
- def self.shrink_quality_of_these_mp3_files(*array)
302
- array.flatten.each {|this_mp3_file|
303
- esystem "lame --mp3input -b 64 #{this_mp3_file}"
231
+ def self.crop_this_video(
232
+ i = 'input.mp4',
233
+ output_file = 'output.mp4'
234
+ )
235
+ [i].flatten.compact.each {|this_video_file|
236
+ esystem 'ffmpeg -i '+
237
+ this_video_file.to_s+
238
+ ' -filter:v "crop=w:h:x:y" '+
239
+ output_file.to_s
304
240
  }
305
241
  end
306
242
 
307
243
  # ========================================================================= #
308
- # === MultimediaParadise.report_how_many_real_videos_are_stored
309
- #
244
+ # === glob
245
+ # ========================================================================= #
246
+ def glob(i)
247
+ Dir[i]
248
+ end
249
+
250
+ # ========================================================================= #
251
+ # === MultimediaParadise::PLAY_ZOOMED
252
+ #
253
+ # If this constant is set to true, then we will play in a zoomed way.
254
+ # ========================================================================= #
255
+ PLAY_ZOOMED = YAML.load_file(
256
+ "#{project_yaml_directory?}configuration/play_zoomed.yml"
257
+ )
258
+
259
+ # ========================================================================= #
260
+ # === MultimediaParadise.verbose_analyse_this_mp3_file_for_id3_tags
261
+ # ========================================================================= #
262
+ def self.verbose_analyse_this_mp3_file_for_id3_tags(this_mp3_file)
263
+ require 'id3lib'
264
+ if this_mp3_file.is_a? Array
265
+ this_mp3_file.each {|entry|
266
+ verbose_analyse_this_mp3_file_for_id3_tags(entry)
267
+ }
268
+ else
269
+ dataset = ID3Lib::Tag.new(this_mp3_file)
270
+ e "#{::Colours.rev}"\
271
+ "The .mp3 file is called: #{sfancy(this_mp3_file)}"
272
+ if dataset.empty?
273
+ e 'Has no id3-tags!'
274
+ else
275
+ # e 'Has some id3-tags.' # <- Dont report this in this case, though.
276
+ # ===================================================================== #
277
+ # Iterate through these entries next.
278
+ # ===================================================================== #
279
+ dataset.each_entry {|inner_hash|
280
+ value = inner_hash[:text].to_s
281
+ case inner_hash[:id]
282
+ # =================================================================== #
283
+ # === :TIT2
284
+ # =================================================================== #
285
+ when :TIT2
286
+ e 'The title is: '+
287
+ Colours.steelblue(value) unless value.empty?
288
+ # =================================================================== #
289
+ # === :TCON
290
+ #
291
+ # The genre.
292
+ # =================================================================== #
293
+ when :TCON
294
+ e 'The genre is: '+
295
+ Colours.steelblue(value) unless value.empty?
296
+ # =================================================================== #
297
+ # === :TYER
298
+ #
299
+ # The year.
300
+ # =================================================================== #
301
+ when :TYER
302
+ e 'The year is: '+
303
+ Colours.steelblue(value) unless value.empty?
304
+ # =================================================================== #
305
+ # === :TPE1
306
+ #
307
+ # The artist.
308
+ # =================================================================== #
309
+ when :TPE1
310
+ e 'The artist is: '+
311
+ Colours.steelblue(value) unless value.empty?
312
+ end
313
+ }
314
+ # pp dataset # <- for debugging.
315
+ end
316
+ end
317
+ end
318
+
319
+ # ========================================================================= #
320
+ # === MultimediaParadise.analyze_this_directory_for_id3_tags
321
+ # ========================================================================= #
322
+ def self.analyze_this_directory_for_id3_tags(i = Dir.pwd)
323
+ require 'id3lib'
324
+ all_files = Dir["#{i}/*.mp3"]
325
+ all_files.each {|this_mp3_file|
326
+ verbose_analyse_this_mp3_file_for_id3_tags(this_mp3_file)
327
+ }
328
+ end
329
+
330
+ # ========================================================================= #
331
+ # === MultimediaParadise.high_quality_transcoding_of_this_video_file
332
+ #
333
+ # This method can be used for high-quality transcoding of a given
334
+ # input video file.
335
+ #
336
+ # - C:V is the video codec of choice
337
+ # - preset is the compression preset (in this case slow for higher
338
+ # quality compression)
339
+ # - CRF is the Constant Rate Factor, which preserves an overall
340
+ # level of quality throughout the file by adjusting each frame's
341
+ # bitrate based on the given quality level. The higher the CRF,
342
+ # the lower the overall quality level.
343
+ # - The video filter flag (-vf) is used to call FFMPEG's pre-bundled
344
+ # video filters.
345
+ # - yadif (Yet Another Deinterlacing Filter) deinterlaces an interlaced
346
+ # input, as progressive video is not only easier to compress and most
347
+ # current computer monitors and televisions are progressive scan.
348
+ # - When encoding with H.264/MPEG-4 AVC, the audio format used is AAC
349
+ # (Advanced Audio Coding); in order to enable FFMPEG's experimental,
350
+ # native AAC encoder.
351
+ # - -strict -2 needs to be added to the command.
352
+ # - An external library such as libfaac can also be used, and -strict
353
+ # -2 can be omitted.
354
+ #
355
+ # ========================================================================= #
356
+ def self.high_quality_transcoding_of_this_video_file(this_video_file)
357
+ output_file = 'OUTPUT_'+this_video_file.
358
+ sub(/#{File.extname(this_video_file)}$/,'')+'.mp4'
359
+ _ = 'ffmpeg -i '+this_video_file+' -c:v libx264 -preset slow '\
360
+ '-crf 18 -vf yadif -strict -2 '+
361
+ output_file
362
+ e
363
+ esystem _
364
+ e
365
+ end; self.instance_eval { alias high_quality_transcoding high_quality_transcoding_of_this_video_file } # === MultimediaParadise.high_quality_transcoding
366
+
367
+ # ========================================================================= #
368
+ # === MultimediaParadise.identify_video
369
+ #
370
+ # Use this to identify a given video or audio file.
371
+ #
372
+ # Another way would be this:
373
+ #
374
+ # mplayer -vo null -ao null -frames 0 -identify POP_America_TheLastUnicorn.mp3
375
+ #
376
+ # You will have to parse this lateron.
377
+ # ========================================================================= #
378
+ def self.identify_video(this_file)
379
+ cmd = "ffmpeg -i #{this_file}"
380
+ e
381
+ e cmd
382
+ e
383
+ result = `{cmd}`
384
+ return result
385
+ end
386
+
387
+ # ========================================================================= #
388
+ # === MultimediaParadise.show_available_audio_formats
389
+ #
390
+ # Use this method if you want to show the available (registered)
391
+ # audio formats.
392
+ # ========================================================================= #
393
+ def self.show_available_audio_formats
394
+ e; AUDIO_FORMATS.each {|entry|
395
+ e " - #{entry}" # It is ok to prepend the '-' since this is for display purposes.
396
+ }; e
397
+ end
398
+
399
+ # ========================================================================= #
400
+ # === MultimediaParadise.show_artist
401
+ #
402
+ # Use this for .mp3 files, via ffmpeg. It will show the artist.
403
+ #
404
+ # Input should be a .mp3 file.
405
+ #
406
+ # Usage example from within ruby code:
407
+ #
408
+ # MultimediaParadise.show_artist('/Depot/Audio/YoutubeMix_VivaldisFourSeasons.mp3')
409
+ # MultimediaParadise.show_artist('/Depot/Audio/Vivaldi_Concerto8.mp3')
410
+ #
411
+ # ========================================================================= #
412
+ def self.show_artist(
413
+ i, report_classname = true
414
+ )
415
+ result = MultimediaParadise.return_artist(i)
416
+ if result.empty?
417
+ opnn if report_classname
418
+ e 'This file does not have any artist-tag.'
419
+ else
420
+ opnn if report_classname
421
+ e "The artist is: #{simp(result)}"
422
+ end
423
+ end
424
+
425
+ # ========================================================================= #
426
+ # === MultimediaParadise.return_artist
427
+ # ========================================================================= #
428
+ def self.return_artist(
429
+ i,
430
+ report_classname = true
431
+ )
432
+ i = i.to_s
433
+ cmd =
434
+ 'ffprobe -loglevel error -show_entries format_tags=artist '\
435
+ '-of default=noprint_wrappers=1:nokey=1 '+i
436
+ result = `#{cmd}`.chomp
437
+ return result
438
+ end
439
+
440
+ # ========================================================================= #
441
+ # === MultimediaParadise.decrease_volume
442
+ #
443
+ # This should decrease audio volume, by using sox.
444
+ #
445
+ # We do this by using the command --volume FACTOR.
446
+ # ========================================================================= #
447
+ def self.decrease_volume(
448
+ of_this_file,
449
+ by_how_much = '0.5'
450
+ )
451
+ run_sys_command 'sox --volume '+
452
+ by_how_much+' '+of_this_file+' AUDIO_REDUCED_'+of_this_file
453
+ end
454
+
455
+ # ========================================================================= #
456
+ # === MultimediaParadise.create_noise_profile
457
+ #
458
+ # Note that this method depends on the external program called "sox".
459
+ #
460
+ # Usage example:
461
+ #
462
+ # MultimediaParadise.create_noise_profile('foobar.mp3')
463
+ #
464
+ # ========================================================================= #
465
+ def self.create_noise_profile(
466
+ of_this_mp3_file
467
+ )
468
+ array_results = []
469
+ [of_this_mp3_file].flatten.compact.each {|work_on_this_mp3_file|
470
+ work_on_this_mp3_file = File.absolute_path(work_on_this_mp3_file)
471
+ filename_without_extension = work_on_this_mp3_file.delete_suffix('.mp3')
472
+ this_profile_file_is_to_be_created = "noise_profile_based_on_#{File.basename(filename_without_extension)}"
473
+ if File.exist?(this_profile_file_is_to_be_created) # Always remove old profiles.
474
+ File.delete(this_profile_file_is_to_be_created)
475
+ end
476
+ cmd_to_run = "sox #{work_on_this_mp3_file} -n noiseprof #{this_profile_file_is_to_be_created}.profile"
477
+ e cmd_to_run
478
+ `#{cmd_to_run}`
479
+ array_results << this_profile_file_is_to_be_created
480
+ }
481
+ return array_results
482
+ end
483
+
484
+ # ========================================================================= #
485
+ # === MultimediaParadise.shrink_quality_of_these_mp3_files
486
+ #
487
+ # This method can be used to batch-shrink several .mp3 files in one go.
488
+ #
489
+ # Usage example:
490
+ #
491
+ # MultimediaParadise.shrink_quality_of_these_mp3_files(Dir['*.mp3'])
492
+ #
493
+ # ========================================================================= #
494
+ def self.shrink_quality_of_these_mp3_files(*array)
495
+ array.flatten.each {|this_mp3_file|
496
+ esystem "lame --mp3input -b 64 #{this_mp3_file}"
497
+ }
498
+ end
499
+
500
+ # ========================================================================= #
501
+ # === MultimediaParadise.report_how_many_real_videos_are_stored
502
+ #
310
503
  # This method will report how many "real" videos are stored in the
311
504
  # file video_collection.yml, which is distributed as part of
312
505
  # this gem. You can, however had, also specify your own .yml
@@ -563,402 +756,167 @@ module MultimediaParadise
563
756
  end
564
757
 
565
758
  # ========================================================================= #
566
- # === MultimediaParadise.to_ts
759
+ # === MultimediaParadise.mpg_to_mp4
760
+ #
761
+ # This is an opinionated method.
567
762
  #
568
- # This will batch-convert all .mp4 files into .ts files.
763
+ # You have to pass the filename to this method, in order to convert
764
+ # the .mpg files into .mp4 files.
569
765
  # ========================================================================= #
570
- def self.to_ts
571
- files = Dir['*.mp4']
572
- files.each {|this_file|
573
- cmd = 'ffmpeg -i '+this_file+' -c copy '\
574
- '-bsf:v h264_mp4toannexb -f mpegts '+
575
- this_file.sub(/#{File.extname(this_file)}$/,'')+
576
- '.ts'
577
-
578
- esystem cmd
766
+ def self.mpg_to_mp4(*i)
767
+ # ======================================================================= #
768
+ # Going with crf 26 - that seems to be a bit better than 25, actually.
769
+ # ======================================================================= #
770
+ crf_value_to_use = '26' # 25-28 should suffice; lower value means higher quality and larger file size.
771
+ result = []
772
+ i.flatten.each {|this_file|
773
+ this_file = File.absolute_path(this_file)
774
+ output_file = File.dirname(this_file)+'/'+
775
+ 'output_'+
776
+ File.basename(this_file).
777
+ delete_suffix(
778
+ File.extname(this_file)
779
+ )+'.mp4'
780
+ _ = 'ffmpeg -i '+this_file.to_s+' -c:v libx265 -c:a libmp3lame '\
781
+ '-crf '+crf_value_to_use.to_s+' '\
782
+ '-preset:v veryslow '+
783
+ output_file
784
+ e
785
+ esystem _
786
+ e
787
+ result << File.absolute_path(output_file)
579
788
  }
789
+ result # We must return the output files here.
580
790
  end
581
791
 
582
792
  # ========================================================================= #
583
- # === MultimediaParadise.set_the_aspect_ratio_of_this_video
584
- #
585
- # This method will set the aspect-ratio of a given video file, via
586
- # ffmpeg. The commandline-flag for this is called -aspect.
587
- #
588
- # Original example:
589
- #
590
- # ffmpeg -i foo.mp4 -aspect 16:9 bar.mp4
591
- #
592
- # Example for the MultimediaParadise namespace:
593
- #
594
- # MultimediaParadise.set_the_aspect_ratio_of_this_video('foo.mpg')
595
- #
596
- # ========================================================================= #
597
- def self.set_the_aspect_ratio_of_this_video(
598
- this_video, use_this_aspect_ratio = '16:9'
599
- )
600
- extension_to_use = File.extname(this_video)
601
- cmd_to_use = 'ffmpeg -i '+this_video+' -aspect '+
602
- use_this_aspect_ratio+' output_'+
603
- this_video.sub(/#{extension_to_use}$/,'')+extension_to_use
604
- e
605
- e cmd_to_use
606
- e
607
- system cmd_to_use
608
- end
609
-
610
- # ========================================================================= #
611
- # === MultimediaParadise.extract_one_image_per_second
612
- #
613
- # This method will extract one-image-per-second from a given
614
- # input video file.
615
- #
616
- # The first argument to this method should be the video file you
617
- # are working with, such as 'foobar.mp4'.
618
- # ========================================================================= #
619
- def self.extract_one_image_per_second(
620
- from_this_video_file = 'my_video.mpeg',
621
- frame_size_to_use = '75x75'
622
- )
623
- extension_to_use = File.extname(from_this_video_file)
624
- _ = 'ffmpeg -i '+from_this_video_file+
625
- ' -r 1 '+ # ← Specify the video-frame here, aka "1 image per second".
626
- '-s '+frame_size_to_use+
627
- ' OUTPUT_'+from_this_video_file.sub(/#{extension_to_use}$/,'')+
628
- extension_to_use
629
- e
630
- esystem _
631
- e
632
- end
633
-
634
- # ========================================================================= #
635
- # === MultimediaParadise.convert_these_images_into_a_video
636
- #
637
- # This method can be used to "assemble" images into a video.
638
- # ========================================================================= #
639
- def self.convert_these_images_into_a_video(*images)
640
- _ = 'ffmpeg -f image2 -i '+images.join(' ').strip+' video.mpg'
641
- esystem _
642
- end
643
-
644
- # ========================================================================= #
645
- # === MultimediaParadise.high_quality_transcoding_of_this_video_file
646
- #
647
- # This method can be used for high-quality transcoding of a given
648
- # input video file.
649
- #
650
- # - C:V is the video codec of choice
651
- # - preset is the compression preset (in this case slow for higher
652
- # quality compression)
653
- # - CRF is the Constant Rate Factor, which preserves an overall
654
- # level of quality throughout the file by adjusting each frame's
655
- # bitrate based on the given quality level. The higher the CRF,
656
- # the lower the overall quality level.
657
- # - The video filter flag (-vf) is used to call FFMPEG's pre-bundled
658
- # video filters.
659
- # - yadif (Yet Another Deinterlacing Filter) deinterlaces an interlaced
660
- # input, as progressive video is not only easier to compress and most
661
- # current computer monitors and televisions are progressive scan.
662
- # - When encoding with H.264/MPEG-4 AVC, the audio format used is AAC
663
- # (Advanced Audio Coding); in order to enable FFMPEG's experimental,
664
- # native AAC encoder.
665
- # - -strict -2 needs to be added to the command.
666
- # - An external library such as libfaac can also be used, and -strict
667
- # -2 can be omitted.
668
- #
669
- # ========================================================================= #
670
- def self.high_quality_transcoding_of_this_video_file(this_video_file)
671
- output_file = 'OUTPUT_'+this_video_file.
672
- sub(/#{File.extname(this_video_file)}$/,'')+'.mp4'
673
- _ = 'ffmpeg -i '+this_video_file+' -c:v libx264 -preset slow '\
674
- '-crf 18 -vf yadif -strict -2 '+
675
- output_file
676
- e
677
- esystem _
678
- e
679
- end; self.instance_eval { alias high_quality_transcoding high_quality_transcoding_of_this_video_file } # === MultimediaParadise.high_quality_transcoding
680
-
681
- # ========================================================================= #
682
- # === MultimediaParadise.identify_video
683
- #
684
- # Use this to identify a given video or audio file.
685
- #
686
- # Another way would be this:
687
- #
688
- # mplayer -vo null -ao null -frames 0 -identify POP_America_TheLastUnicorn.mp3
793
+ # === MultimediaParadise.return_the_mpeg_layer_from_this_mp3_file
689
794
  #
690
- # You will have to parse this lateron.
795
+ # This method will make use of the binary called "mpg123".
691
796
  # ========================================================================= #
692
- def self.identify_video(this_file)
693
- cmd = "ffmpeg -i #{this_file}"
694
- e
695
- e cmd
696
- e
697
- result = `{cmd}`
797
+ def self.return_the_mpeg_layer_from_this_mp3_file(i)
798
+ cmd = "mpg123 -t #{i} 2>&1"
799
+ result = `#{cmd}`
800
+ splitted = result.split("\n")
801
+ selected = splitted.select {|line|
802
+ line.start_with? 'MPEG ' # Obtain the MPEG layer here.
803
+ }.uniq
804
+ result = selected.first # Pick the first result here.
805
+ # ======================================================================= #
806
+ # We may have to clean up that result a little bit still.
807
+ # ======================================================================= #
808
+ if result and result.include?(' ') and result.include?('III')
809
+ result = result[0 .. (result.index('III')+2)]
810
+ end
698
811
  return result
699
812
  end
700
813
 
701
814
  # ========================================================================= #
702
- # === MultimediaParadise.show_available_audio_formats
703
- #
704
- # Use this method if you want to show the available (registered)
705
- # audio formats.
706
- # ========================================================================= #
707
- def self.show_available_audio_formats
708
- e; AUDIO_FORMATS.each {|entry|
709
- e " - #{entry}" # It is ok to prepend the '-' since this is for display purposes.
710
- }; e
711
- end
712
-
713
- # ========================================================================= #
714
- # === MultimediaParadise.show_artist
715
- #
716
- # Use this for .mp3 files, via ffmpeg. It will show the artist.
815
+ # === MultimediaParadise.loop_this_video
717
816
  #
718
- # Input should be a .mp3 file.
817
+ # This method can be used to loop a video, via ffmpeg.
719
818
  #
720
- # Usage example from within ruby code:
819
+ # A commandline variant for this would look as follows:
721
820
  #
722
- # MultimediaParadise.show_artist('/Depot/Audio/YoutubeMix_VivaldisFourSeasons.mp3')
723
- # MultimediaParadise.show_artist('/Depot/Audio/Vivaldi_Concerto8.mp3')
821
+ # ffmpeg -stream_loop 3 -i Tata.webm -c copy output.webm
724
822
  #
725
823
  # ========================================================================= #
726
- def self.show_artist(
727
- i, report_classname = true
728
- )
729
- result = MultimediaParadise.return_artist(i)
730
- if result.empty?
731
- opnn if report_classname
732
- e 'This file does not have any artist-tag.'
733
- else
734
- opnn if report_classname
735
- e "The artist is: #{simp(result)}"
736
- end
737
- end
738
-
739
- # ========================================================================= #
740
- # === MultimediaParadise.return_artist
741
- # ========================================================================= #
742
- def self.return_artist(
743
- i,
744
- report_classname = true
745
- )
746
- i = i.to_s
747
- cmd =
748
- 'ffprobe -loglevel error -show_entries format_tags=artist '\
749
- '-of default=noprint_wrappers=1:nokey=1 '+i
750
- result = `#{cmd}`.chomp
824
+ def self.loop_this_video(this_video = 'foobar.webm', n_times = '5x')
825
+ result = []
826
+ [this_video].flatten.compact.each {|work_on_this_video_file|
827
+ n_times = n_times.to_s.delete('x').sub(/ times/,'')
828
+ output_file = "output_#{work_on_this_video_file}"
829
+ result << output_file
830
+ cmd = "ffmpeg -stream_loop #{n_times} -i #{work_on_this_video_file} -c copy #{output_file}"
831
+ esystem cmd
832
+ }
751
833
  return result
752
834
  end
753
835
 
754
836
  # ========================================================================= #
755
- # === MultimediaParadise.load_yaml
756
- # ========================================================================= #
757
- def self.load_yaml(i)
758
- YAML.load_file(i)
759
- end
760
-
761
- # ========================================================================= #
762
- # === MultimediaParadise.open_yaml_file
763
- #
764
- # This will open my video collection.
837
+ # === MultimediaParadise.bin_dir?
765
838
  # ========================================================================= #
766
- def self.open_yaml_file(
767
- i = FILE_VIDEO_COLLECTION
768
- )
769
- esystem "bluefish #{i}"
770
- end
839
+ def self.bin_dir?
840
+ RbConfig::CONFIG['bindir'].to_s+'/' # Ensure trailing '/'.
841
+ end; self.instance_eval { alias bindir? bin_dir? } # === MultimediaParadise.bindir?
771
842
 
772
843
  # ========================================================================= #
773
- # === MultimediaParadise.flip_video_to_the_left
844
+ # === MultimediaParadise.copy_bin_directory
774
845
  #
775
- # This toplevel-method can be used to flip a video to the left,
776
- # that is, to rotate it by -90 degrees.
846
+ # This method can be used to copy the content of the bin/ directory
847
+ # onto the current working directory.
777
848
  #
778
- # It will tap into ffmpeg for this task.
779
- # ========================================================================= #
780
- def self.flip_video_to_the_left(i)
781
- ffmpeg_flip_video_to_the_left(i)
782
- end
783
-
784
- # ========================================================================= #
785
- # === MultimediaParadise.flip_video_to_the_right
849
+ # Usage example from within ruby code:
786
850
  #
787
- # This toplevel-method can be used to flip a video to the right,
788
- # that is, to rotate it by +90 degrees.
789
- # ========================================================================= #
790
- def self.flip_video_to_the_right(i)
791
- ffmpeg_flip_video_to_the_right(i)
792
- end
793
-
794
- # ========================================================================= #
795
- # === glob
796
- # ========================================================================= #
797
- def glob(i)
798
- Dir[i]
799
- end
800
-
801
- # ========================================================================= #
802
- # === video_collection?
803
- # ========================================================================= #
804
- def video_collection?
805
- ::MultimediaParadise.file_video_collection
806
- end
807
-
808
- # ========================================================================= #
809
- # === MultimediaParadise::PLAY_ZOOMED
851
+ # require 'multimedia_paradise'; MultimediaParadise.copy_bin_directory
810
852
  #
811
- # If this constant is set to true, then we will play in a zoomed way.
812
853
  # ========================================================================= #
813
- PLAY_ZOOMED = YAML.load_file(
814
- "#{PROJECT_BASE_DIRECTORY}configuration/play_zoomed.yml"
815
- )
816
-
817
- # ========================================================================= #
818
- # === MultimediaParadise.verbose_analyse_this_mp3_file_for_id3_tags
819
- # ========================================================================= #
820
- def self.verbose_analyse_this_mp3_file_for_id3_tags(this_mp3_file)
821
- require 'id3lib'
822
- if this_mp3_file.is_a? Array
823
- this_mp3_file.each {|entry|
824
- verbose_analyse_this_mp3_file_for_id3_tags(entry)
825
- }
826
- else
827
- dataset = ID3Lib::Tag.new(this_mp3_file)
828
- e "#{::Colours.rev}"\
829
- "The .mp3 file is called: #{sfancy(this_mp3_file)}"
830
- if dataset.empty?
831
- e 'Has no id3-tags!'
832
- else
833
- # e 'Has some id3-tags.' # <- Dont report this in this case, though.
834
- # ===================================================================== #
835
- # Iterate through these entries next.
836
- # ===================================================================== #
837
- dataset.each_entry {|inner_hash|
838
- value = inner_hash[:text].to_s
839
- case inner_hash[:id]
840
- # =================================================================== #
841
- # === :TIT2
842
- # =================================================================== #
843
- when :TIT2
844
- e 'The title is: '+
845
- Colours.steelblue(value) unless value.empty?
846
- # =================================================================== #
847
- # === :TCON
848
- #
849
- # The genre.
850
- # =================================================================== #
851
- when :TCON
852
- e 'The genre is: '+
853
- Colours.steelblue(value) unless value.empty?
854
- # =================================================================== #
855
- # === :TYER
856
- #
857
- # The year.
858
- # =================================================================== #
859
- when :TYER
860
- e 'The year is: '+
861
- Colours.steelblue(value) unless value.empty?
862
- # =================================================================== #
863
- # === :TPE1
864
- #
865
- # The artist.
866
- # =================================================================== #
867
- when :TPE1
868
- e 'The artist is: '+
869
- Colours.steelblue(value) unless value.empty?
854
+ def self.copy_bin_directory
855
+ file_installed_binaries = "#{project_base_directory?}"\
856
+ "yaml/internal/installed_binaries.yml"
857
+ mkdir('bin/')
858
+ cd('bin/')
859
+ if File.exist? file_installed_binaries
860
+ e 'Making use of the file '+sfile(file_installed_binaries)+'.'
861
+ install_these_binaries = YAML.load_file(file_installed_binaries)
862
+ installation_directory = `gem env`.split("\n").select {|line| # Check for INSTALLATION DIRECTORY: /root/.gem
863
+ line.include? 'INSTALLATION DIRECTORY:'
864
+ }.first.
865
+ scan(/INSTALLATION DIRECTORY: (.+)$/).flatten.first
866
+ install_these_binaries.each {|entry|
867
+ target = installation_directory+'/bin/'+entry
868
+ if File.exist? target
869
+ e "Copying the file #{target} into the current working "\
870
+ "directory next."
871
+ copy_file(target, Dir.pwd)
872
+ else
873
+ # ================================================================= #
874
+ # Since as of January 2023 first try the bin_dir, before giving up.
875
+ # ================================================================= #
876
+ target = MultimediaParadise.bin_dir?+File.basename(entry)
877
+ if File.exist? target
878
+ e "Copying the file #{target} into the current working "\
879
+ "directory next."
880
+ copy_file(target, Dir.pwd)
881
+ else
882
+ no_file_exists_at(target)
870
883
  end
871
- }
872
- # pp dataset # <- for debugging.
873
- end
884
+ end
885
+ }
874
886
  end
875
887
  end
876
888
 
877
889
  # ========================================================================= #
878
- # === MultimediaParadise.analyze_this_directory_for_id3_tags
879
- # ========================================================================= #
880
- def self.analyze_this_directory_for_id3_tags(i = Dir.pwd)
881
- require 'id3lib'
882
- all_files = Dir["#{i}/*.mp3"]
883
- all_files.each {|this_mp3_file|
884
- verbose_analyse_this_mp3_file_for_id3_tags(this_mp3_file)
885
- }
886
- end
887
-
888
- # ========================================================================= #
889
- # === MultimediaParadise.compress_this_ogg_file
890
+ # === MultimediaParadise.extract_one_image_per_second
890
891
  #
891
- # This method will use a sampling rate of 22050 Hz. This should be
892
- # perfectly adequate for speech-related audio, but I also found it
893
- # to work well when compressing a tetris.ogg file (for the game
894
- # tetris).
892
+ # This method will extract one-image-per-second from a given
893
+ # input video file.
894
+ #
895
+ # The first argument to this method should be the video file you
896
+ # are working with, such as 'foobar.mp4'.
895
897
  # ========================================================================= #
896
- def self.compress_this_ogg_file(i = 'foobar.ogg')
897
- _ = 'ffmpeg -i '+entry+' '\
898
- '-c:a libvorbis -ab 32k '\
899
- '-ar 22050'\
900
- ' OUTPUT_'+i
898
+ def self.extract_one_image_per_second(
899
+ from_this_video_file = 'my_video.mpeg',
900
+ frame_size_to_use = '75x75'
901
+ )
902
+ extension_to_use = File.extname(from_this_video_file)
903
+ _ = 'ffmpeg -i '+from_this_video_file+
904
+ ' -r 1 '+ # ← Specify the video-frame here, aka "1 image per second".
905
+ '-s '+frame_size_to_use+
906
+ ' OUTPUT_'+from_this_video_file.sub(/#{extension_to_use}$/,'')+
907
+ extension_to_use
901
908
  e
902
909
  esystem _
903
910
  e
904
911
  end
905
912
 
906
- # ========================================================================= #
907
- # === MultimediaParadise.try_to_rename_kde_konsole_tab
908
- # ========================================================================= #
909
- def self.try_to_rename_kde_konsole_tab(
910
- new_title = '_',
911
- try_to_rename_the_kde_konsole_tab = TRY_TO_RENAME_THE_KDE_KONSOLE_TAB
912
- )
913
- if try_to_rename_the_kde_konsole_tab
914
- begin
915
- require 'roebe/requires/require_kde_konsole.rb'
916
- rescue LoadError
917
- e 'roebe/requires/require_kde_konsole.rb is not available'
918
- end
919
- if Object.const_defined?(:Roebe) and
920
- Roebe.respond_to?(:rename_konsole)
921
- Roebe.rename_konsole(new_title)
922
- end
923
- end
924
- end; self.instance_eval { alias rename_kde_konsole try_to_rename_kde_konsole_tab } # === MultimediaParadise.rename_kde_konsole
925
- self.instance_eval { alias do_rename_konsole try_to_rename_kde_konsole_tab } # === MultimediaParadise.do_rename_konsole
926
- self.instance_eval { alias rename_kde_konsole_tab try_to_rename_kde_konsole_tab } # === MultimediaParadise.rename_kde_konsole_tab
927
-
928
- # ========================================================================= #
929
- # === MultimediaParadise.crop_this_video
930
- #
931
- # This method can be used to crop a particular video file, via
932
- # ffmpeg.
933
- #
934
- # The raw ffmpeg-command would go like something like this:
935
- #
936
- # ffmpeg -i input.mp4 -filter:v "crop=out_w:out_h:x:y" output.mp4
937
- #
938
- # These variables are:
939
- #
940
- # → out_w is the width of the output rectangle
941
- # → out_h is the height of the output rectangle
942
- # → x and y specify the top left corner of the output rectangle
943
- # → output.mp4 is the output file
944
- #
945
- # ========================================================================= #
946
- def self.crop_this_video(
947
- i = 'input.mp4',
948
- output_file = 'output.mp4'
949
- )
950
- [i].flatten.compact.each {|this_video_file|
951
- esystem 'ffmpeg -i '+
952
- this_video_file.to_s+
953
- ' -filter:v "crop=w:h:x:y" '+
954
- output_file.to_s
955
- }
956
- end
957
-
958
913
  end
959
914
 
960
915
  if __FILE__ == $PROGRAM_NAME
916
+ alias e puts
917
+ require 'multimedia_paradise/version/version.rb'
961
918
  include MultimediaParadise
962
- map_number_to_videofile
963
- puts 'The version of the MultimediaParadise project is: '+version?
964
- end # rb shared.rb
919
+ #map_number_to_videofile
920
+ e 'The version of the MultimediaParadise project is: '+
921
+ MultimediaParadise.version?
922
+ end # rb toplevel_methods.rb