multimedia_paradise 1.1.344

Sign up to get free protection for your applications and to get access to all the features.
Files changed (382) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +2720 -0
  3. data/bin/audio_player +12 -0
  4. data/bin/auto_title +7 -0
  5. data/bin/convert_audio_to_mp4video_with_image +7 -0
  6. data/bin/cut_audio +7 -0
  7. data/bin/cut_multimedia +7 -0
  8. data/bin/extract_audio +7 -0
  9. data/bin/extract_images_from_this_video_file +7 -0
  10. data/bin/ffmpeg_merge +7 -0
  11. data/bin/file_duration +7 -0
  12. data/bin/gtk_radio +7 -0
  13. data/bin/has_audio +7 -0
  14. data/bin/loop_this_video +7 -0
  15. data/bin/merge_avi_files +7 -0
  16. data/bin/merge_mp3 +7 -0
  17. data/bin/missing_video_files +7 -0
  18. data/bin/movie_searcher +7 -0
  19. data/bin/mp3_to_opus +7 -0
  20. data/bin/mpg_to_mp4 +7 -0
  21. data/bin/mplayer_wrapper +7 -0
  22. data/bin/multimedia_information +11 -0
  23. data/bin/multimedia_paradise +9 -0
  24. data/bin/multimedia_paradise_sinatra +7 -0
  25. data/bin/play_random_simpsons_video +7 -0
  26. data/bin/playlist +7 -0
  27. data/bin/random_video +7 -0
  28. data/bin/remove_audio +9 -0
  29. data/bin/remove_last_second +7 -0
  30. data/bin/remove_subtitles +7 -0
  31. data/bin/reverse_video +7 -0
  32. data/bin/rubio +58 -0
  33. data/bin/tag_mp3_files +7 -0
  34. data/bin/to_aiff +10 -0
  35. data/bin/to_mp4 +7 -0
  36. data/bin/verbose_analyse_this_mp3_file_for_id3_tags +9 -0
  37. data/bin/video_codec +7 -0
  38. data/bin/video_information +8 -0
  39. data/bin/video_player +11 -0
  40. data/bin/video_thumbnail +7 -0
  41. data/bin/video_to_images +7 -0
  42. data/bin/vp9 +9 -0
  43. data/bin/waveform +73 -0
  44. data/doc/CHANGELOG.md +44 -0
  45. data/doc/LINKS.md +6 -0
  46. data/doc/MOTIVATION_FOR_THIS_PROJECT.md +22 -0
  47. data/doc/MergingVideoLectures.md +12 -0
  48. data/doc/README.gen +2658 -0
  49. data/doc/Readme_for_the_cut_audio_component.md +168 -0
  50. data/doc/todo/todo_for_the_GUIs.md +0 -0
  51. data/doc/todo/todo_for_the_multimedia_paradise_project.md +111 -0
  52. data/lib/multimedia_paradise/audio/audio_player/audio_player.rb +1143 -0
  53. data/lib/multimedia_paradise/audio/audio_tag_reader/README.md +7 -0
  54. data/lib/multimedia_paradise/audio/audio_tag_reader/audio_tag_reader.rb +503 -0
  55. data/lib/multimedia_paradise/audio/base.rb +67 -0
  56. data/lib/multimedia_paradise/audio/compress.rb +97 -0
  57. data/lib/multimedia_paradise/audio/create_m3u_playlist.rb +256 -0
  58. data/lib/multimedia_paradise/audio/extract_audio/constants.rb +37 -0
  59. data/lib/multimedia_paradise/audio/extract_audio/extract_audio.rb +417 -0
  60. data/lib/multimedia_paradise/audio/file_duration/constants.rb +53 -0
  61. data/lib/multimedia_paradise/audio/file_duration/file_duration.rb +606 -0
  62. data/lib/multimedia_paradise/audio/genres/boogie.rb +35 -0
  63. data/lib/multimedia_paradise/audio/genres/concerts.rb +35 -0
  64. data/lib/multimedia_paradise/audio/genres/constants.rb +53 -0
  65. data/lib/multimedia_paradise/audio/genres/eurodance.rb +35 -0
  66. data/lib/multimedia_paradise/audio/genres/genre.rb +696 -0
  67. data/lib/multimedia_paradise/audio/genres/hip_hop.rb +35 -0
  68. data/lib/multimedia_paradise/audio/genres/italian_songs.rb +35 -0
  69. data/lib/multimedia_paradise/audio/genres/the_1980s.rb +35 -0
  70. data/lib/multimedia_paradise/audio/genres/trance.rb +35 -0
  71. data/lib/multimedia_paradise/audio/lyrics_fetcher.rb +238 -0
  72. data/lib/multimedia_paradise/audio/merge_audio_files.rb +114 -0
  73. data/lib/multimedia_paradise/audio/modify_year_of_audio_file.rb +136 -0
  74. data/lib/multimedia_paradise/audio/n_audio_songs.rb +208 -0
  75. data/lib/multimedia_paradise/audio/play_all_audio_files.rb +122 -0
  76. data/lib/multimedia_paradise/audio/playlist/playlist.rb +1636 -0
  77. data/lib/multimedia_paradise/audio/remove_audio.rb +98 -0
  78. data/lib/multimedia_paradise/audio/remove_last_second.rb +83 -0
  79. data/lib/multimedia_paradise/audio/report_missing_id.rb +131 -0
  80. data/lib/multimedia_paradise/audio/streamripper/constants.rb +51 -0
  81. data/lib/multimedia_paradise/audio/streamripper/streamripper_wrapper.rb +279 -0
  82. data/lib/multimedia_paradise/audio/to_mp3.rb +138 -0
  83. data/lib/multimedia_paradise/audio/to_ogg.rb +104 -0
  84. data/lib/multimedia_paradise/audio/wav_to_mp3.rb +87 -0
  85. data/lib/multimedia_paradise/audio/waveform/class.rb +341 -0
  86. data/lib/multimedia_paradise/audio/waveform/constants.rb +38 -0
  87. data/lib/multimedia_paradise/audio/waveform/log.rb +101 -0
  88. data/lib/multimedia_paradise/autoinclude.rb +3 -0
  89. data/lib/multimedia_paradise/autoinclude_remove_audio.rb +6 -0
  90. data/lib/multimedia_paradise/base/base.rb +34 -0
  91. data/lib/multimedia_paradise/base/colours.rb +391 -0
  92. data/lib/multimedia_paradise/base/commandline_arguments.rb +60 -0
  93. data/lib/multimedia_paradise/base/constants.rb +19 -0
  94. data/lib/multimedia_paradise/base/encoding.rb +31 -0
  95. data/lib/multimedia_paradise/base/misc.rb +665 -0
  96. data/lib/multimedia_paradise/base/namespace.rb +36 -0
  97. data/lib/multimedia_paradise/base/time.rb +25 -0
  98. data/lib/multimedia_paradise/colours/colours.rb +89 -0
  99. data/lib/multimedia_paradise/commandline/menu.rb +463 -0
  100. data/lib/multimedia_paradise/configuration/play_zoomed.yml +1 -0
  101. data/lib/multimedia_paradise/constants/constants.rb +23 -0
  102. data/lib/multimedia_paradise/constants/conversions.rb +62 -0
  103. data/lib/multimedia_paradise/constants/directory_constants.rb +139 -0
  104. data/lib/multimedia_paradise/constants/encodings.rb +26 -0
  105. data/lib/multimedia_paradise/constants/file_constants.rb +176 -0
  106. data/lib/multimedia_paradise/constants/misc.rb +80 -0
  107. data/lib/multimedia_paradise/constants/my_video_directory.rb +30 -0
  108. data/lib/multimedia_paradise/constants/namespace.rb +14 -0
  109. data/lib/multimedia_paradise/constants/newline.rb +14 -0
  110. data/lib/multimedia_paradise/constants/video_filetypes.rb +27 -0
  111. data/lib/multimedia_paradise/constants/web_constants.rb +150 -0
  112. data/lib/multimedia_paradise/conversions/README.md +2 -0
  113. data/lib/multimedia_paradise/conversions/conversions.rb +930 -0
  114. data/lib/multimedia_paradise/css/project.css +15 -0
  115. data/lib/multimedia_paradise/data/asoundrc +12 -0
  116. data/lib/multimedia_paradise/ffmpeg/README.md +2 -0
  117. data/lib/multimedia_paradise/ffmpeg/ffmpeg.rb +620 -0
  118. data/lib/multimedia_paradise/gui/fox/play_from_radio_station.rb +75 -0
  119. data/lib/multimedia_paradise/gui/glimmer/rubio/model/bookmark.rb +61 -0
  120. data/lib/multimedia_paradise/gui/glimmer/rubio/model/player.rb +226 -0
  121. data/lib/multimedia_paradise/gui/glimmer/rubio/model/radio_browser.rb +57 -0
  122. data/lib/multimedia_paradise/gui/glimmer/rubio/model/radio_presenter.rb +132 -0
  123. data/lib/multimedia_paradise/gui/glimmer/rubio/model/station.rb +48 -0
  124. data/lib/multimedia_paradise/gui/glimmer/rubio/view/radio.rb +296 -0
  125. data/lib/multimedia_paradise/gui/gosu/video_player/video_player.rb +109 -0
  126. data/lib/multimedia_paradise/gui/gtk2/multimedia_converter/multimedia_converter.rb +33 -0
  127. data/lib/multimedia_paradise/gui/gtk2/notebook.rb +144 -0
  128. data/lib/multimedia_paradise/gui/gtk2/play_video_from_my_collection/play_video_from_my_collection.rb +43 -0
  129. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/README.md +12 -0
  130. data/lib/multimedia_paradise/gui/gtk2/simple_play_widget/simple_play_widget.rb +40 -0
  131. data/lib/multimedia_paradise/gui/gtk2/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +42 -0
  132. data/lib/multimedia_paradise/gui/gtk2/youtube_downloader/youtube_downloader.rb +32 -0
  133. data/lib/multimedia_paradise/gui/gtk3/lyrics/lyrics.rb +0 -0
  134. data/lib/multimedia_paradise/gui/gtk3/multimedia_converter/multimedia_converter.rb +34 -0
  135. data/lib/multimedia_paradise/gui/gtk3/multimedia_notebook/multimedia_notebook.rb +34 -0
  136. data/lib/multimedia_paradise/gui/gtk3/play_video_from_my_collection/play_video_from_my_collection.rb +34 -0
  137. data/lib/multimedia_paradise/gui/gtk3/playlist/playlist.rb +34 -0
  138. data/lib/multimedia_paradise/gui/gtk3/simple_play_widget/simple_play_widget.rb +38 -0
  139. data/lib/multimedia_paradise/gui/gtk3/video_editor/video_editor.rb +34 -0
  140. data/lib/multimedia_paradise/gui/gtk3/video_player/video_player.rb +34 -0
  141. data/lib/multimedia_paradise/gui/gtk3/webcam_widget/webcam_widget.rb +425 -0
  142. data/lib/multimedia_paradise/gui/gtk3/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +36 -0
  143. data/lib/multimedia_paradise/gui/gtk3/youtube_channels/youtube_channels.rb +210 -0
  144. data/lib/multimedia_paradise/gui/gtk3/youtube_downloader/youtube_downloader.rb +32 -0
  145. data/lib/multimedia_paradise/gui/gui_base.rb +92 -0
  146. data/lib/multimedia_paradise/gui/libui/change_metadata_widget/change_metadata_widget.rb +115 -0
  147. data/lib/multimedia_paradise/gui/libui/cut_multimedia/cut_multimedia.rb +119 -0
  148. data/lib/multimedia_paradise/gui/libui/lyrics/lyrics.rb +67 -0
  149. data/lib/multimedia_paradise/gui/libui/simple_play_widget/simple_play_widget.rb +119 -0
  150. data/lib/multimedia_paradise/gui/libui/video_player/video_player.rb +81 -0
  151. data/lib/multimedia_paradise/gui/libui/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio.rb +126 -0
  152. data/lib/multimedia_paradise/gui/libui/youtube_channels/youtube_channels.rb +116 -0
  153. data/lib/multimedia_paradise/gui/libui/youtube_downloader/youtube_downloader.rb +107 -0
  154. data/lib/multimedia_paradise/gui/shared_code/lyrics/lyrics_module.rb +0 -0
  155. data/lib/multimedia_paradise/gui/shared_code/multimedia_converter/multimedia_converter_module.rb +478 -0
  156. data/lib/multimedia_paradise/gui/shared_code/multimedia_notebook/multimedia_notebook_module.rb +171 -0
  157. data/lib/multimedia_paradise/gui/shared_code/play_video_from_my_collection/play_video_from_my_collection_module.rb +464 -0
  158. data/lib/multimedia_paradise/gui/shared_code/playlist/playlist_module.rb +151 -0
  159. data/lib/multimedia_paradise/gui/shared_code/simple_play_widget/simple_play_widget_module.rb +257 -0
  160. data/lib/multimedia_paradise/gui/shared_code/sound_effect_widget/sound_effect_widget_module.rb +0 -0
  161. data/lib/multimedia_paradise/gui/shared_code/video_editor/video_editor_module.rb +287 -0
  162. data/lib/multimedia_paradise/gui/shared_code/video_player/video_player_module.rb +185 -0
  163. data/lib/multimedia_paradise/gui/shared_code/widget_increase_or_decrease_audio/widget_increase_or_decrease_audio_module.rb +310 -0
  164. data/lib/multimedia_paradise/gui/shared_code/youtube_downloader/youtube_downloader_module.rb +339 -0
  165. data/lib/multimedia_paradise/gui/tk/tk_multimedia_wrapper.rb +60 -0
  166. data/lib/multimedia_paradise/gui/universal_widgets/change_metadata_widget/README.md +3 -0
  167. data/lib/multimedia_paradise/gui/universal_widgets/change_metadata_widget/change_metadata_widget.rb +751 -0
  168. data/lib/multimedia_paradise/gui/universal_widgets/cut_multimedia/cut_multimedia.rb +657 -0
  169. data/lib/multimedia_paradise/gui/universal_widgets/information_about_a_mp3_file/information_about_a_mp3_file.rb +597 -0
  170. data/lib/multimedia_paradise/gui/universal_widgets/lyrics/lyrics.rb +265 -0
  171. data/lib/multimedia_paradise/gui/universal_widgets/radio/radio.rb +1364 -0
  172. data/lib/multimedia_paradise/gui/universal_widgets/sound_effect_widget/sound_effect_widget.rb +265 -0
  173. data/lib/multimedia_paradise/gui/universal_widgets/tag_mp3_files/tag_mp3_files.config +6 -0
  174. data/lib/multimedia_paradise/gui/universal_widgets/tag_mp3_files/tag_mp3_files.rb +2429 -0
  175. data/lib/multimedia_paradise/gui/universal_widgets/video_collection/video_collection.rb +246 -0
  176. data/lib/multimedia_paradise/help/help.rb +75 -0
  177. data/lib/multimedia_paradise/images/MULTIMEDIA.jpg +0 -0
  178. data/lib/multimedia_paradise/images/MULTIMEDIA_PARADISE_ID_TAG_GUI_IN_RUBY_GTK3.png +0 -0
  179. data/lib/multimedia_paradise/images/MULTIMEDIA_PARADISE_LOGO.png +0 -0
  180. data/lib/multimedia_paradise/images/UK_flag.png +0 -0
  181. data/lib/multimedia_paradise/images/US_flag.png +0 -0
  182. data/lib/multimedia_paradise/images/austrian_flag.png +0 -0
  183. data/lib/multimedia_paradise/images/french_flag.png +0 -0
  184. data/lib/multimedia_paradise/images/german_flag.png +0 -0
  185. data/lib/multimedia_paradise/images/radio_image.png +0 -0
  186. data/lib/multimedia_paradise/images/trance.png +0 -0
  187. data/lib/multimedia_paradise/java/AudioPlayer.class +0 -0
  188. data/lib/multimedia_paradise/java/AudioPlayer.java +103 -0
  189. data/lib/multimedia_paradise/java/README.md +3 -0
  190. data/lib/multimedia_paradise/misc/long_format_to_milliseconds_converter.rb +182 -0
  191. data/lib/multimedia_paradise/misc/milliseconds_to_long_format_converter.rb +186 -0
  192. data/lib/multimedia_paradise/multimedia/analyse_multimedia_file.rb +180 -0
  193. data/lib/multimedia_paradise/multimedia/avisynth/README.md +4 -0
  194. data/lib/multimedia_paradise/multimedia/avisynth/avisynth_code.avs +471 -0
  195. data/lib/multimedia_paradise/multimedia/base.rb +60 -0
  196. data/lib/multimedia_paradise/multimedia/chord.rb +174 -0
  197. data/lib/multimedia_paradise/multimedia/convert_audio_to_video_with_image.rb +171 -0
  198. data/lib/multimedia_paradise/multimedia/cut_multimedia/10_minutes_chop.rb +29 -0
  199. data/lib/multimedia_paradise/multimedia/cut_multimedia/15_minutes_chop.rb +29 -0
  200. data/lib/multimedia_paradise/multimedia/cut_multimedia/30_minutes_chop.rb +29 -0
  201. data/lib/multimedia_paradise/multimedia/cut_multimedia/5_minutes_chop.rb +29 -0
  202. data/lib/multimedia_paradise/multimedia/cut_multimedia/cut_multimedia.rb +2021 -0
  203. data/lib/multimedia_paradise/multimedia/cut_multimedia/evaluate_from_this_file.rb +79 -0
  204. data/lib/multimedia_paradise/multimedia/cut_multimedia/interactive_menu.rb +525 -0
  205. data/lib/multimedia_paradise/multimedia/interactive_shell.rb +84 -0
  206. data/lib/multimedia_paradise/multimedia/merge_multimedia.rb +127 -0
  207. data/lib/multimedia_paradise/multimedia/note.rb +500 -0
  208. data/lib/multimedia_paradise/multimedia/play_from_this_list.rb +163 -0
  209. data/lib/multimedia_paradise/multimedia/read_meta_tags.rb +173 -0
  210. data/lib/multimedia_paradise/multimedia/simulate_youtube_playlist.rb +209 -0
  211. data/lib/multimedia_paradise/multimedia/start_length_duration.rb +205 -0
  212. data/lib/multimedia_paradise/multimedia/video_downloader/video_downloader.rb +135 -0
  213. data/lib/multimedia_paradise/project/project.rb +47 -0
  214. data/lib/multimedia_paradise/requires/require_audio_files.rb +74 -0
  215. data/lib/multimedia_paradise/requires/require_cut_multimedia.rb +7 -0
  216. data/lib/multimedia_paradise/requires/require_extract_audio.rb +7 -0
  217. data/lib/multimedia_paradise/requires/require_file_duration.rb +7 -0
  218. data/lib/multimedia_paradise/requires/require_streamripper.rb +7 -0
  219. data/lib/multimedia_paradise/requires/require_the_audio_player.rb +7 -0
  220. data/lib/multimedia_paradise/requires/require_the_multimedia_paradise_project.rb +38 -0
  221. data/lib/multimedia_paradise/requires/require_the_sinatra_components.rb +7 -0
  222. data/lib/multimedia_paradise/requires/require_toplevel_methods_files.rb +25 -0
  223. data/lib/multimedia_paradise/requires/require_video_files.rb +25 -0
  224. data/lib/multimedia_paradise/requires/require_video_player.rb +7 -0
  225. data/lib/multimedia_paradise/sinatra/app.rb +318 -0
  226. data/lib/multimedia_paradise/sinatra/embeddable_interface.rb +379 -0
  227. data/lib/multimedia_paradise/sound_effects/README.md +12 -0
  228. data/lib/multimedia_paradise/sound_effects/cat_meow.mp3 +0 -0
  229. data/lib/multimedia_paradise/sound_effects/channel_opened.mp3 +0 -0
  230. data/lib/multimedia_paradise/sound_effects/phone_ring.mp3 +0 -0
  231. data/lib/multimedia_paradise/statistics/README.md +5 -0
  232. data/lib/multimedia_paradise/statistics/video.rb +84 -0
  233. data/lib/multimedia_paradise/toplevel_cut_audio.rb +16 -0
  234. data/lib/multimedia_paradise/toplevel_methods/analyze_audio_stream.rb +31 -0
  235. data/lib/multimedia_paradise/toplevel_methods/chop_into_segments_of_n_seconds_size.rb +32 -0
  236. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_five_minutes.rb +22 -0
  237. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_n_seconds.rb +92 -0
  238. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_ten_minutes.rb +22 -0
  239. data/lib/multimedia_paradise/toplevel_methods/chop_off_first_two_minutes.rb +24 -0
  240. data/lib/multimedia_paradise/toplevel_methods/codecs.rb +50 -0
  241. data/lib/multimedia_paradise/toplevel_methods/copy_and_merge_this_video_n_times.rb +51 -0
  242. data/lib/multimedia_paradise/toplevel_methods/copy_file.rb +18 -0
  243. data/lib/multimedia_paradise/toplevel_methods/create_video_from_this_audio.rb +65 -0
  244. data/lib/multimedia_paradise/toplevel_methods/cut_from_to.rb +156 -0
  245. data/lib/multimedia_paradise/toplevel_methods/delay_audio.rb +31 -0
  246. data/lib/multimedia_paradise/toplevel_methods/denoise.rb +90 -0
  247. data/lib/multimedia_paradise/toplevel_methods/deshake.rb +43 -0
  248. data/lib/multimedia_paradise/toplevel_methods/e.rb +16 -0
  249. data/lib/multimedia_paradise/toplevel_methods/encode_this_video.rb +49 -0
  250. data/lib/multimedia_paradise/toplevel_methods/ensure_that_the_output_directory_exists.rb +27 -0
  251. data/lib/multimedia_paradise/toplevel_methods/esystem.rb +43 -0
  252. data/lib/multimedia_paradise/toplevel_methods/files_and_directories.rb +92 -0
  253. data/lib/multimedia_paradise/toplevel_methods/flip_and_rotate.rb +58 -0
  254. data/lib/multimedia_paradise/toplevel_methods/has_audio.rb +48 -0
  255. data/lib/multimedia_paradise/toplevel_methods/increase_volume_of_this_audio_file.rb +61 -0
  256. data/lib/multimedia_paradise/toplevel_methods/is_a_multimedia_file.rb +27 -0
  257. data/lib/multimedia_paradise/toplevel_methods/is_audio_file.rb +27 -0
  258. data/lib/multimedia_paradise/toplevel_methods/is_image_file.rb +31 -0
  259. data/lib/multimedia_paradise/toplevel_methods/is_on_roebe.rb +17 -0
  260. data/lib/multimedia_paradise/toplevel_methods/is_video_file.rb +62 -0
  261. data/lib/multimedia_paradise/toplevel_methods/merge_multimedia_file.rb +331 -0
  262. data/lib/multimedia_paradise/toplevel_methods/merge_these_videos.rb +106 -0
  263. data/lib/multimedia_paradise/toplevel_methods/misc.rb +964 -0
  264. data/lib/multimedia_paradise/toplevel_methods/opn.rb +24 -0
  265. data/lib/multimedia_paradise/toplevel_methods/output_directory.rb +61 -0
  266. data/lib/multimedia_paradise/toplevel_methods/player_in_use.rb +80 -0
  267. data/lib/multimedia_paradise/toplevel_methods/query_the_audio_codec_of_this_file.rb +24 -0
  268. data/lib/multimedia_paradise/toplevel_methods/radio.rb +381 -0
  269. data/lib/multimedia_paradise/toplevel_methods/rds.rb +24 -0
  270. data/lib/multimedia_paradise/toplevel_methods/return_all_video_files.rb +64 -0
  271. data/lib/multimedia_paradise/toplevel_methods/return_data_from_video_collection_file_for_this_entry.rb +38 -0
  272. data/lib/multimedia_paradise/toplevel_methods/return_duration_of_this_multimedia_file.rb +27 -0
  273. data/lib/multimedia_paradise/toplevel_methods/return_full_name_for_video_at_this_position.rb +54 -0
  274. data/lib/multimedia_paradise/toplevel_methods/return_path_to_random_simpsons_video_file.rb +43 -0
  275. data/lib/multimedia_paradise/toplevel_methods/return_random_video_file_from_the_video_collection.rb +73 -0
  276. data/lib/multimedia_paradise/toplevel_methods/return_screen_resolution.rb +24 -0
  277. data/lib/multimedia_paradise/toplevel_methods/run_sys_command.rb +30 -0
  278. data/lib/multimedia_paradise/toplevel_methods/scale_video.rb +27 -0
  279. data/lib/multimedia_paradise/toplevel_methods/set_title_of.rb +65 -0
  280. data/lib/multimedia_paradise/toplevel_methods/slow_down_this_video_file.rb +33 -0
  281. data/lib/multimedia_paradise/toplevel_methods/start_screencast.rb +70 -0
  282. data/lib/multimedia_paradise/toplevel_methods/subtitles.rb +59 -0
  283. data/lib/multimedia_paradise/toplevel_methods/to_flac.rb +30 -0
  284. data/lib/multimedia_paradise/toplevel_methods/to_mp4.rb +24 -0
  285. data/lib/multimedia_paradise/toplevel_methods/total_duration.rb +35 -0
  286. data/lib/multimedia_paradise/toplevel_methods/use_lame_codec.rb +32 -0
  287. data/lib/multimedia_paradise/toplevel_methods/video_dataset.rb +76 -0
  288. data/lib/multimedia_paradise/version/version.rb +28 -0
  289. data/lib/multimedia_paradise/video/all_videos.rb +101 -0
  290. data/lib/multimedia_paradise/video/capture_screen.rb +285 -0
  291. data/lib/multimedia_paradise/video/check_numbers.rb +215 -0
  292. data/lib/multimedia_paradise/video/columbo/columbo.rb +139 -0
  293. data/lib/multimedia_paradise/video/copy_missing_video_files.rb +292 -0
  294. data/lib/multimedia_paradise/video/copy_random_video.rb +98 -0
  295. data/lib/multimedia_paradise/video/correct_video_numbers.rb +263 -0
  296. data/lib/multimedia_paradise/video/create_dvd.rb +50 -0
  297. data/lib/multimedia_paradise/video/create_video_thumbnails.rb +137 -0
  298. data/lib/multimedia_paradise/video/encode_video.rb +81 -0
  299. data/lib/multimedia_paradise/video/ffmpeg_options.rb +156 -0
  300. data/lib/multimedia_paradise/video/find_video/find_video.rb +668 -0
  301. data/lib/multimedia_paradise/video/fix_married_with_children_videos.rb +70 -0
  302. data/lib/multimedia_paradise/video/genres.rb +333 -0
  303. data/lib/multimedia_paradise/video/guess_video_name.rb +189 -0
  304. data/lib/multimedia_paradise/video/imdb_rating/imdb_rating.rb +133 -0
  305. data/lib/multimedia_paradise/video/mike_hammer/mike_hammer.rb +74 -0
  306. data/lib/multimedia_paradise/video/missing_video_files/missing_video_files.rb +286 -0
  307. data/lib/multimedia_paradise/video/movie_searcher.rb +281 -0
  308. data/lib/multimedia_paradise/video/mplayer_wrapper.rb +504 -0
  309. data/lib/multimedia_paradise/video/n_videos.rb +142 -0
  310. data/lib/multimedia_paradise/video/play_random_file.rb +91 -0
  311. data/lib/multimedia_paradise/video/play_random_realvideo.rb +92 -0
  312. data/lib/multimedia_paradise/video/prepare_video_lecture.rb +267 -0
  313. data/lib/multimedia_paradise/video/random_video.rb +302 -0
  314. data/lib/multimedia_paradise/video/registered_video_file.rb +131 -0
  315. data/lib/multimedia_paradise/video/remove_metadata.rb +52 -0
  316. data/lib/multimedia_paradise/video/rename_video_file.rb +149 -0
  317. data/lib/multimedia_paradise/video/report_local_videos.rb +106 -0
  318. data/lib/multimedia_paradise/video/report_missing_videos_in_the_yaml_file.rb +107 -0
  319. data/lib/multimedia_paradise/video/resolution.rb +194 -0
  320. data/lib/multimedia_paradise/video/reverse_video.rb +74 -0
  321. data/lib/multimedia_paradise/video/simpsons.rb +129 -0
  322. data/lib/multimedia_paradise/video/smart_animals/smart_animals.rb +188 -0
  323. data/lib/multimedia_paradise/video/speed_up_video.rb +135 -0
  324. data/lib/multimedia_paradise/video/split_this_video.rb +126 -0
  325. data/lib/multimedia_paradise/video/srt_regex.rb +211 -0
  326. data/lib/multimedia_paradise/video/store_available_video_files.rb +138 -0
  327. data/lib/multimedia_paradise/video/the_simpsons/README.md +9 -0
  328. data/lib/multimedia_paradise/video/the_simpsons/good_the_simpsons_episodes.rb +107 -0
  329. data/lib/multimedia_paradise/video/the_simpsons/the_simpsons.rb +87 -0
  330. data/lib/multimedia_paradise/video/video.rb +14 -0
  331. data/lib/multimedia_paradise/video/video_encoding_settings.rb +57 -0
  332. data/lib/multimedia_paradise/video/video_information.rb +445 -0
  333. data/lib/multimedia_paradise/video/video_metadata.rb +132 -0
  334. data/lib/multimedia_paradise/video/video_player.rb +580 -0
  335. data/lib/multimedia_paradise/video/video_renamer.rb +161 -0
  336. data/lib/multimedia_paradise/video/watermark.rb +282 -0
  337. data/lib/multimedia_paradise/video/youtube/youtube.rb +17 -0
  338. data/lib/multimedia_paradise/video/youtube_embedder.rb +235 -0
  339. data/lib/multimedia_paradise/yaml/audio_formats.yml +14 -0
  340. data/lib/multimedia_paradise/yaml/best_songs_in_an_era/eurodance/top20.yml +28 -0
  341. data/lib/multimedia_paradise/yaml/game_shows/ruck_zuck/ruck_zuck.yml +25 -0
  342. data/lib/multimedia_paradise/yaml/genres/1980s.yml +198 -0
  343. data/lib/multimedia_paradise/yaml/genres/README.md +5 -0
  344. data/lib/multimedia_paradise/yaml/genres/boogie.yml +68 -0
  345. data/lib/multimedia_paradise/yaml/genres/concerts.yml +29 -0
  346. data/lib/multimedia_paradise/yaml/genres/eurodance.yml +456 -0
  347. data/lib/multimedia_paradise/yaml/genres/hip_hop.yml +49 -0
  348. data/lib/multimedia_paradise/yaml/genres/italian_songs.yml +53 -0
  349. data/lib/multimedia_paradise/yaml/genres/trance.yml +167 -0
  350. data/lib/multimedia_paradise/yaml/good_horror_movies/good_horror_movies.yml +12 -0
  351. data/lib/multimedia_paradise/yaml/good_movie_actors/good_movie_actors.yml +6 -0
  352. data/lib/multimedia_paradise/yaml/image_formats.yml +8 -0
  353. data/lib/multimedia_paradise/yaml/internal/README.md +2 -0
  354. data/lib/multimedia_paradise/yaml/internal/installed_binaries.yml +31 -0
  355. data/lib/multimedia_paradise/yaml/lyrics.yml +6323 -0
  356. data/lib/multimedia_paradise/yaml/movie_reviews/the_hateful_eight_september_2016.md +305 -0
  357. data/lib/multimedia_paradise/yaml/music_genres.yml +51 -0
  358. data/lib/multimedia_paradise/yaml/playlist.yml +130 -0
  359. data/lib/multimedia_paradise/yaml/radio/README.md +5 -0
  360. data/lib/multimedia_paradise/yaml/radio/radio_stations.yml +359 -0
  361. data/lib/multimedia_paradise/yaml/song_tags.yml +818 -0
  362. data/lib/multimedia_paradise/yaml/tales_from_the_crypt/tales_from_the_crypt.yml +426 -0
  363. data/lib/multimedia_paradise/yaml/tom_and_jerry/README.md +2 -0
  364. data/lib/multimedia_paradise/yaml/tom_and_jerry/tom_and_jerry_episodes.yml +27 -0
  365. data/lib/multimedia_paradise/yaml/tv_channels/tv_channels.yml +46 -0
  366. data/lib/multimedia_paradise/yaml/use_this_video_player.yml +1 -0
  367. data/lib/multimedia_paradise/yaml/video/video.yml +26 -0
  368. data/lib/multimedia_paradise/yaml/video_collection/video_collection.yml +1933 -0
  369. data/lib/multimedia_paradise/yaml/video_encoding_settings.yml +62 -0
  370. data/lib/multimedia_paradise/yaml/video_filter_aliases.yml +221 -0
  371. data/lib/multimedia_paradise/yaml/youtube/alltagsgeschichte/alltagsgeschichte.yml +190 -0
  372. data/lib/multimedia_paradise/yaml/youtube/songs/README.md +3 -0
  373. data/lib/multimedia_paradise/yaml/youtube/songs/songs.yml +6 -0
  374. data/lib/multimedia_paradise/yaml/youtube_playlist/youtube_playlist.yml +6 -0
  375. data/lib/multimedia_paradise.rb +5 -0
  376. data/multimedia_paradise.gemspec +74 -0
  377. data/test/testing_audio_player.rb +15 -0
  378. data/test/testing_ffmpeg_options.rb +14 -0
  379. data/test/testing_file_duration.rb +17 -0
  380. data/test/testing_modify_year_of_audio_file.rb +14 -0
  381. data/test/testing_multimedia_paradise_project.rb +151 -0
  382. metadata +560 -0
data/README.md ADDED
@@ -0,0 +1,2720 @@
1
+ [![forthebadge](https://forthebadge.com/images/badges/built-with-love.svg)](https://www.gobolinux.org/)
2
+ [![forthebadge](https://forthebadge.com/images/badges/made-with-ruby.svg)](https://www.ruby-lang.org/en/)
3
+ [![Gem Version](https://badge.fury.io/rb/multimedia_paradise.svg)](https://badge.fury.io/rb/multimedia_paradise)
4
+
5
+ This gem was <b>last updated</b> on the <span style="color: darkblue; font-weight: bold">23.01.2024</span> (dd.mm.yyyy notation), at <span style="color: steelblue; font-weight: bold">07:25:13</span> o'clock.
6
+
7
+ # MultimediaParadise - a toolset project for audio and video related data
8
+
9
+ <img src="https://i.imgur.com/Qh4Fve1.png" style="margin: 1em; margin-left: 2.5em">
10
+
11
+ The **multimedia paradise** project bundles together code that can be
12
+ used for "multimedia data" - in particular for **audio** and **video** files.
13
+
14
+ Most of the functionality found within the **multimedia paradise**
15
+ projects depends on <b>ffmpeg</b>, but in principle the code in the
16
+ main module called **MultimediaParadise** should work with other
17
+ toolkits as well, if a toolkit supports certain actions (such as
18
+ <b>sox</b>). As is often the case, support for other toolkits depends
19
+ on time investment - and time availability - of the main author of
20
+ this project, but in principle support for other toolkits can be
21
+ added as-is, at any moment in time. It is just that **ffmpeg** is
22
+ really good, so other toolkits will have a hard time competing
23
+ against it.
24
+
25
+ For multimedia-related purposes, **ffmpeg** is a really excellent
26
+ project. Thus, the MultimediaParadise gem will focus on **ffmpeg**
27
+ by default.
28
+
29
+ You can obtain a copy of ffmpeg from the following URL:
30
+
31
+ https://www.ffmpeg.org/download.html
32
+
33
+ ## Installation of the MultimediaParadise project
34
+
35
+ There are several ways how to install this project, including using
36
+ oldschool **setup.rb** - but I recommend the following way, for
37
+ simplicity, on any modern system:
38
+
39
+ gem install multimedia_paradise --user-install
40
+
41
+ The reason as to why I recommend the **--user-install** option is to be
42
+ used is because the various files under the **bin/** subdirectory that
43
+ are part of this gem will be made available in your home directory
44
+ (under e. g. ~/.gem/ruby/2.5.0/bin or whatever your local ruby
45
+ version is). That way you can easily add that directory to $PATH
46
+ or not, and make use of these files if you want to - and if not,
47
+ just ignore the bin/ subdirectory of this gem altogether.
48
+
49
+ You can find out the paths used by **gem** via:
50
+
51
+ gem environment
52
+
53
+ Note that even if you can not find such a bin/ subdirectory on your
54
+ system, these files are distributed within the **multimedia_paradise**
55
+ gem itself as such, so just extract the gem, then copy the bin/ files
56
+ to wherever you want to. There is more than one way to do
57
+ things! If you still have a hard time doing so, you can use a
58
+ toplevel method that will copy all bin/ files into the current
59
+ working directory. So, for instance, create a directory at:
60
+
61
+ mkdir /tmp/multimedia_paradise # just an example
62
+
63
+ Then start **irb** and issue:
64
+
65
+ require 'multimedia_paradise'
66
+ MultimediaParadise.copy_bin_directory
67
+
68
+ This will create a directory called **bin/** and then proceed
69
+ to copy all bin/ files into that directory. This is just a
70
+ convenience workaround if --user-dir does not work on your
71
+ system, for whatever the reason. (Note that this assumes
72
+ that these bin/ entries are in your HOME directory under
73
+ bin/ which may not always be the case; I have no idea why
74
+ this does not work anymore. It used to work in the past.
75
+ Ask the rubygems maintainers what they broke over the
76
+ years if this does not work for you. :P But, even in that
77
+ case, you can just download the .gem file from rubygems.org
78
+ and extract it on your own, and then you will 100% have
79
+ the bin/ hierarchy there.)
80
+
81
+ It is recommended to install **ffmpeg** and have it made
82
+ available on your system - ffmpeg really is a great project,
83
+ and the multimedia_paradise gem taps into the functionality
84
+ made available by ffmpeg. In many ways the multimedia_paradise
85
+ gem is a convenient wrapper over **some** of ffmpeg's
86
+ functionality.
87
+
88
+ In the next subsections on this webpage, several different
89
+ examples will be shown that may be usable (and useful) by
90
+ a user, to <b>benefit</b> from the code made available via
91
+ the MultimediaParadise project. Keep in mind that this
92
+ project tries to be a <b>helpful toolset</b> project,
93
+ not necessarily a professional-grade software suite.
94
+
95
+ ## Removing the audio from a local video file
96
+
97
+ Let us begin with a fairly simply use case here: say that you
98
+ want to **remove the audio from a local video file**.
99
+
100
+ So if you have such a use case that requires of you to
101
+ **remove audio from a local video file**, use the
102
+ following **API**:
103
+
104
+ require 'multimedia_paradise/audio/remove_audio.rb'
105
+ MultimediaParadise.remove_audio(path_to_the_file_goes_in_here)
106
+
107
+ Specific example for this:
108
+
109
+ MultimediaParadise.remove_audio('/tmp/foo.avi')
110
+ MultimediaParadise.remove_audio('foobar.mp4')
111
+
112
+ This functionality depends on an installed **ffmpeg**, as
113
+ previously pointed out. If anyone happens to know of a
114
+ pure ruby variant only, let me know - I may add this to
115
+ the method, as an alternative.
116
+
117
+ The above method essentially issues the following command:
118
+
119
+ ffmpeg -i foobar.mp4 -an -vcodec copy /Depot/jj/output_foobar.mp4
120
+
121
+ So only the video stream is copied, due to the <b>-an</b> option.
122
+
123
+ Note that the ruby-gtk3 bindings of **video_editor.rb**, distributed
124
+ within this project, makes use of this functionality as well.
125
+
126
+ Note that an executable exists for this functionality as well, at
127
+ <b>bin/remove_audio</b>. So you can simply issue this on the
128
+ commandline:
129
+
130
+ remove_audio foobar.mp4
131
+
132
+ ## Streamripper support
133
+
134
+ There is code support for <b>streamripper</b>, just a tiny wrapper.
135
+
136
+ This can be invoked like so:
137
+
138
+ MultimediaParadise.streamripper
139
+
140
+ This depends on the file <b>streamripper_wrapper.rb</b> which
141
+ is just a tiny, pure-ruby "wrapper" over streamripper. (It
142
+ really only directly calls the streampripper binary, so
143
+ nothing fancy.)
144
+
145
+ ## Modifying the timestamps of .srt files
146
+
147
+ The file <b>srt_regex.rb</b> - situated
148
+ at **multimedia_paradise/video/srt_regex.rb** - can be used if
149
+ you need to batch-modify .srt files, when they have the wrong
150
+ timestamp, for instance.
151
+
152
+ This was exactly the reason why I wrote that class a long
153
+ time ago - some .srt files may have a wrong offset, and
154
+ so we need to correct them.
155
+
156
+ Note that this class is quite old and the code quality is not
157
+ as high as other classes since I wrote it a long time ago. I may
158
+ improve on it eventually, but for the time being, assume that
159
+ it isn't one of the best classes in this project. I did
160
+ not have a use case for .srt files for many years - most
161
+ of the time I listen to english these days and then I don't
162
+ even need .srt files. I have had a few videos in chinese
163
+ (mandarin), and for these .srt files are useful - but even
164
+ that usage declined, so out of 1000 video files only 3-4
165
+ may still be in chinese, so I rarely need to use this
166
+ class anymore. As a consequence I did not invest much
167
+ timeo into improving it lateron.
168
+
169
+ ## Increasing the volume of an audio file
170
+
171
+ You can use the toplevel-level method for increasing the volume
172
+ of an audio file:
173
+
174
+ MultimediaParadise.increase_volume_of_this_audio_file()
175
+
176
+ The **first argument** to this method should be the name of the file
177
+ that you wish to modify or the name of the files. This is usually
178
+ a file such as foobar.mp3 or similar.
179
+
180
+ The **second argument** is the modified percentage value that is
181
+ given to -v (and to **sox**). For example, if you pass in 2.0,
182
+ then the volume of the audio file at hand will be **increased
183
+ twofold**. If it is 3.0, then it will be increased threefold,
184
+ and so on.
185
+
186
+ Since the name of the method is "increase_volume", that particular
187
+ method can not be used to decrease the volume (via negative
188
+ floats such as -2.0).
189
+
190
+ ## Screen capture
191
+
192
+ If you want to capture the screen, that is, to record what
193
+ is happening, have a look at the class called
194
+ <b>MultimediaParadise::CaptureScreen</b>, in the file
195
+ **multimedia_paradise/video/capture_screen.rb**.
196
+
197
+ ## Autoinclude the main namespace
198
+
199
+ Since April 2014 you can autoinclude this project's main
200
+ namespace (toplevel **MultimediaParadise constant**)
201
+ by using the following ruby code:
202
+
203
+ require 'multimedia_paradise/autoinclude'
204
+
205
+ ## Using the executable bin/mpa
206
+
207
+ **mpa** is a small wrapper over mpv (or mplayer).
208
+
209
+ It is tailored to my own local videoset, which I store in
210
+ a yaml file. I am not sure how to best have other people
211
+ use mpa without the .yml file, but at the worst, it
212
+ is possible to just use bin/multimedia_paradise to play
213
+ an existing local video or audio file.
214
+
215
+ ## Guessing video names
216
+
217
+ I use a **.yml** file to keep track of registered video files.
218
+
219
+ I also needed a class that tells me the most likely name of a
220
+ video file, e. g. if the input is "Ninja", then this class
221
+ should report all Ninja video files, properly sorted, according
222
+ to the information contained in that .yml file. (This of course
223
+ requires that this genre is registered in that .yml file.)
224
+
225
+ **class MultimediaParadise::GuessVideoName** does precisely
226
+ that. Input the given search term at hand, such as **horror**
227
+ for horror movies, and it should hopefully report some information
228
+ that may be useful in order to find/name the video file at hand.
229
+
230
+ Note that this depends on a properly formatted .yml file; and
231
+ ideally you would create your own .yml file, with your own
232
+ tags, videos and so forth.
233
+
234
+ The **format** of the .yml file should be like this:
235
+
236
+ a) The number of the video file at hand, as an **Integer** value, such as 1, 2, 3 and so forth.
237
+ b) A **hash** that describes at the least the 'title', but may also contain entries such as <b>imdb:</b> and so forth.
238
+
239
+ ## Finding local videos
240
+
241
+ The file <b>find_video.rb</b> can be of help here as it will
242
+ try to locate local videos.
243
+
244
+ This is optimized towards my own dataset compiled about
245
+ videos; in the future, I will most likely provide a way
246
+ so that other people can also use their own dataset.
247
+ (The dataset I use is a simple yaml file storing all
248
+ information about the local videos.)
249
+
250
+ ## Delaying the audio of a video-file
251
+
252
+ FFmpeg allows you to easily delay the audio of a video file.
253
+
254
+ MultimediaParadise has this included as well, via:
255
+
256
+ MultimediaParadise.delay_audio()
257
+
258
+ The first argument to this should be the name of the file
259
+ that you wish to manipulate, such as <b>foobar.mp4</b>.
260
+
261
+ The second argument is the amount of seconds for the delay,
262
+ such as 5.53 seconds.
263
+
264
+ A new video-file will be generated as a consequence, if all
265
+ goes well.
266
+
267
+ ## Denoising audio/video
268
+
269
+ This subsection is about <b>removing noise from a multimedia file</b>.
270
+
271
+ **Noise** in this context refers to **unwanted audio**, such as
272
+ scratching on a blackboard during a university lecture, and similar
273
+ unwanted noises.
274
+
275
+ First, this functionality was needed because I inherited **audio recordings**
276
+ that were made via a cheap mp3-recorder from like **+10 years ago** or so,
277
+ say, the year 2009 - something like that.
278
+
279
+ The human voice has a **frequency range** between **300Hz** - **3000Hz**.
280
+
281
+ The **noise** in these files was extremey disturbing and distracting, and
282
+ I wanted to get rid of it, in order to more easily hear the voice of the
283
+ speaker. This also included increasing the volume as well, but that is
284
+ for another subsection.
285
+
286
+ The subsection here will additionally report some of my findings from back
287
+ then - as a **memo**.
288
+
289
+ A simple **filter-strategy** is to **first apply highpass**, and then
290
+ **lowpass**, via **ffmpeg**, such as in this way:
291
+
292
+ ffmpeg -i foobar.mp3 -af "lowpass=f=3000, highpass=f=200" output.mp3
293
+
294
+ Your local file comes first, such as the file <b>foobar.mp3</b>. This
295
+ should remove some of the noise that you may find in a recording, but
296
+ you may have to tweak the values a little in order to get the most
297
+ out of it.
298
+
299
+ Note that you can use **ffplay** to see the effect of this:
300
+
301
+ ffplay INPUT_FILE -af lowpass=3000,highpass=200
302
+ ffplay foobar.mp3 -af lowpass=4000,highpass=200
303
+ ffplay foobar.mp3 -af lowpass=2000,highpass=200
304
+
305
+ I integrated this functionality into **MultimediaParadise**, via the
306
+ following simple API:
307
+
308
+ MultimediaParadise.denoise('foobar.mp3')
309
+
310
+ This is the default use case, by just supplying the name/path to the
311
+ audio file in question.
312
+
313
+ The second argument to this method is the **lowpass value**; the
314
+ third argument is for the **highpass value**:
315
+
316
+ MultimediaParadise.denoise('foobar.mp3', '250', '2000')
317
+
318
+ This, surprisingly enough, worked. But I do not think it is
319
+ the ideal value.
320
+
321
+ For more information, see the following blog entry from 2017:
322
+
323
+ https://manerosss.wordpress.com/2017/07/24/ffmpeg-%C2%B7-apply-a-filter-to-enhance-voice-by-removing-low-and-high-frequency-noises/
324
+
325
+ If you need to find out which values are best, you can use <b>ffplay</b>
326
+ such as in this way:
327
+
328
+ ffplay INPUT -af lowpass=3000,highpass=200
329
+
330
+ ## Creating a screencast with multimedia_paradise and FFMPEG
331
+
332
+ Code in the file **multimedia_paradise/toplevel_methods/screencast.rb** can
333
+ be used to record a screencast (on Linux).
334
+
335
+ The API is as follows:
336
+
337
+ MultimediaParadise.start_screencast
338
+
339
+ The method accepts several parameters - if you need fine tuning then
340
+ have a look at that file.
341
+
342
+ Presently only video without audio can be recorded, but there are
343
+ tutorials out there that enable recording of audio as well. I will
344
+ have a look into this at a later time (<- written in September 2018).
345
+
346
+ ## Query the audio codec of a video file
347
+
348
+ You can use this top-level API to determine the audio codec of a
349
+ video file:
350
+
351
+ MultimediaParadise.query_the_audio_codec_of_this_file()
352
+ MultimediaParadise.query_the_audio_codec()
353
+ MultimediaParadise.audio_codec?()
354
+
355
+ All variants listed above work; the last option is the shortest
356
+ one, apparently.
357
+
358
+ The argument should be the path to a locally existing videofile.
359
+
360
+ Say that your file is at **/Depot/foobar.avi** then the ruby code
361
+ may look like this:
362
+
363
+ require 'multimedia_paradise'
364
+ uses_this_codec = MultimediaParadise.audio_codec?('/Depot/foobar.avi') # => ["aac"]
365
+
366
+ Note that this functionality **depends on ffmpeg** right now, so make
367
+ sure to install **ffmpeg** first.
368
+
369
+ ## Converting into .mp3 format
370
+
371
+ You can use class **MultimediaParadise::Audio::ToMp3** to convert
372
+ e. g. a **.wav** file into a **.mp3** file:
373
+
374
+ MultimediaParadise::Audio::ToMp3.new('path_to_wav.waf')
375
+
376
+ As this may be a bit cumbersome to type, there exists a simpler
377
+ **top-level method** to convert an audio-file into the **.mp3
378
+ format**:
379
+
380
+ MultimediaParadise.to_mp3(*input_files_here)
381
+ MultimediaParadise.to_mp3( %( foo.wav bar.wav ) )
382
+
383
+ ## ffmpeg options
384
+
385
+ This subsection just shows a few options for ffmpeg; I added this mostly
386
+ because I tend to be quite forgetful. That way I can have a quick
387
+ overview on the homepage of this gem here.
388
+
389
+ |Commandline flag | Example | Implementation Status
390
+ |-----------------|------------------------|----------------------------------------------------------------------------------------|
391
+ | **-s** | **-s 500×500** | convert the video into a **width x height** ratio, of 500 x 500 pixel |
392
+ | **-vcodec** | **-vcodec mpeg4** | specify which video-codec is to be used, e. g. for the conversion of a video file |
393
+
394
+ ## Playing several multimedia-files from a list/file
395
+
396
+ You can pass a list of files that the MultimediaParadise project
397
+ should play.
398
+
399
+ The toplevel method is **MultimediaParadise.play_this_list()**,
400
+ so for example:
401
+
402
+ MultimediaParadise.play_this_list '
403
+
404
+ /Users/x/VIDEO/Cartoons/Simpsons-09/Treehouse_Of_Horror_VIII.m4v
405
+ /Users/x/VIDEO/Cartoons/Simpsons-09/The_Joy_Of_Sect.m4v
406
+ /Users/x/VIDEO/Cartoons/Simpsons-08/The_Springfield_Files.m4v
407
+
408
+ '
409
+
410
+ Empty lines will be ignored, so the method will only play these
411
+ entries if they are not empty.
412
+
413
+ The alias **MultimediaParadise.play_from_this_list()** would also
414
+ work, by the way.
415
+
416
+ I needed this functionality because sometimes other classes written
417
+ in ruby may show, on the commandline, such a flat list, via a long
418
+ String broken by newlines.
419
+
420
+ ## Environment variables for the MultimediaParadise project
421
+
422
+ The MultimediaParadise project is tailored to my own needs primarily,
423
+ which means that other people may not necessarily benefit from the
424
+ project as much. Additionally, as of December 2018, there are some
425
+ hardcoded paths, which makes this even worse. I have decided in
426
+ December 2018 that this approach will change in the future.
427
+
428
+ For the time being, you can use certain ENV (environment) flags to
429
+ specify where your audio/video files are kept. This assumes that
430
+ you have **one central directory** for these files; respectively
431
+ up to two, if you keep your audio and video files **separate**.
432
+
433
+ For specifying where your **local video files** reside, you can use the
434
+ constant called **MULTIMEDIA_PARADISE_DEPOT_VIDEO**. Simply
435
+ set this, in your shell, to be the path to the directory where
436
+ your video files may be, such as in:
437
+
438
+ export MULTIMEDIA_PARADISE_DEPOT_VIDEO=/opt/videos
439
+
440
+ A similar constant exists for audio files; simply set
441
+ **MULTIMEDIA_PARADISE_DEPOT_AUDIO**.
442
+
443
+ export MULTIMEDIA_PARADISE_DEPOT_AUDIO=/opt/my_songs
444
+
445
+ ## Genre support of video files
446
+
447
+ If you have a .yml file that keeps your video files
448
+ sorted, then you can also use a <b>genre:</b> tag
449
+ identifier to classify the video at hand.
450
+
451
+ For example, the movie <b>The Blade Runner</b> may have an associated
452
+ genre called <b>Science Fiction</b>. The movie <b>Poltergeist</b> may
453
+ have a genre tag called <b>Horror</b> and so on.
454
+
455
+ Once the genre-tagging has been done, we can search
456
+ for these genres on the commandline, via class
457
+ <b>VideoGenres</b>.
458
+
459
+ See its --help option for commands.
460
+
461
+ video_genres --help
462
+
463
+ If you wish to find out which science fiction movies
464
+ are registered, do:
465
+
466
+ video_genres --genre="Science Fiction"
467
+
468
+ You can also use a shorter variant, via a Pseudo-Regex:
469
+
470
+ video_genres "/Science Fiction/"
471
+
472
+ Or the horror genre:
473
+
474
+ video_genres "/Horror/"
475
+
476
+ The "" can be omitted it seems (tested this on July 2021):
477
+
478
+ video_genres /Horror/
479
+
480
+ Some shortcuts exist if the above is too cumbersome. For example,
481
+ all science fiction movies could also be shown via this way:
482
+
483
+ video_genres --science-fiction
484
+
485
+ To see the available video genres, do this:
486
+
487
+ video_genres --available-video-genres
488
+
489
+ It you want to play a **random** horror movie, provided that you
490
+ have these registered tags, you can do the following:
491
+
492
+ video_genres --play-random-video-from-this-genre=horror
493
+
494
+ Keep in mind that this depends on the information stored
495
+ in the file **video_collection.yml**. This is catering to
496
+ my own use case, so you may want to populate this with your
497
+ own dataset.
498
+
499
+ ## Copying and merging the same video
500
+
501
+ If you sort of wish to "duplicate" a video, but append this
502
+ onto an existing one, then you can use this method:
503
+
504
+ MultimediaParadise.copy_and_merge_this_video_n_times
505
+
506
+ The first argument should be the existing video file; the
507
+ second argument should be how many times it should be
508
+ "repeated", which should be a number. For example, the
509
+ number 5 means that the video will be merged onto itself
510
+ 4 times, thus creating a video that is 5x the length (all
511
+ with the same content).
512
+
513
+ There are alternatives to this, such as looping the same
514
+ video; but I wanted to really be able to have the same
515
+ video be played over and over again, even though this
516
+ made the size larger.
517
+
518
+ ## MultimediaParadise::AnalyseMultimediaFile
519
+
520
+ class **MultimediaParadise::AnalyseMultimediaFile** can be used
521
+ to analyse multimedia files (e. g. audio and video files),
522
+ on the commandline.
523
+
524
+ I needed this because **ffmpeg -i** alone was tiresome to
525
+ read.
526
+
527
+
528
+
529
+ ## Flipping and rotating video files
530
+
531
+ FFMpeg can easily flip video files. MultimediaParadise supports this
532
+ functionality too, through the file
533
+ <b>multimedia_paradise/toplevel_methods/flip_and_rotate.rb</b>.
534
+
535
+ Horizontal and vertical flipping is supported through these
536
+ two **toplevel APIs**:
537
+
538
+ MultimediaParadise.horizontal_flip()
539
+ MultimediaParadise.vertical_flip()
540
+
541
+ The latter variant also has a simpler, more intuitive API:
542
+
543
+ MultimediaParadise.flip_upside_down()
544
+
545
+ So essentially, you picture a video, and then simply flip
546
+ the top to the bottom, and the bottom to the top. Easy-peasy.
547
+
548
+ The **first argument** to this method should be the name/path
549
+ to an existing video file.
550
+
551
+ You can also rotate a video file by 90° via this API:
552
+
553
+ MultimediaParadise.rotate_this_video_file_by_90_degrees('foo.mpg')
554
+
555
+ Since as of March 2019, two more methods were added to flip a video
556
+ (rotate a video) clockwise and counter-clockwise, by 90° each:
557
+
558
+ MultimediaParadise.flip_video_to_the_right
559
+ MultimediaParadise.flip_video_to_the_left
560
+
561
+ So the older method **MultimediaParadise.rotate_this_video_file_by_90_degrees()**
562
+ is essentially the same as the newer method **MultimediaParadise.flip_video_to_the_right**.
563
+
564
+ ## Merging audio files together
565
+
566
+ **class MultimediaParadise::MergeAudioFiles** can be used to merge different
567
+ audio files together. If no specific input argument is provided then this
568
+ class will scan for all audio files in the current working directory and all
569
+ subdirectories, then merge these together into a new file called **output.mp3**.
570
+
571
+ I needed this functionality so that I could put lectures together into a single
572
+ file - made it easier to listen to a single file, rather than find them all
573
+ spread out.
574
+
575
+ ## Toplevel cutting multimedia files
576
+
577
+ This subsection deals with cutting multimedia files, that is,
578
+ to chop a longer file into one (or several) smaller files.
579
+
580
+ The primary method for this is called **MultimediaParadise.cut_from_to()**,
581
+ but you can also use a few aliases to this method, such as
582
+ **MultimediaParadise.cut()**.
583
+
584
+ The API is flexible.
585
+
586
+ Let's first show a few examples:
587
+
588
+ MultimediaParadise.cut_from_to('00:00:01-00:25:10', this_file: 'Tales_from_the_crypt_S05E10_Came_the_Dawn_1993.mp4')
589
+ MultimediaParadise.cut_from_to('00:02:23 / 00:28:04', this_file: 'Tales_from_the_crypt_S05E10_Came_the_Dawn_1993.mp4')
590
+ MultimediaParadise.cut(to: '00:22:50', this_file: 'TALES_FROM_THE_CRYPT/Tales_from_the_crypt_S06E11_Surprise_Party.mkv')
591
+
592
+ These are somewhat equivalent.
593
+
594
+ The simplest way may be to pass, as **first argument**, a String to
595
+ the method, denoting the start position and the end position, in
596
+ HH:MM:SS format. But you can also decide to use a Hash instead,
597
+ such as the third example shows.
598
+
599
+ Do note that if you decide to use a String, you can either use
600
+ the '-' variant or a ' / ' variant. The latter is the default
601
+ display format for the mpv video/audio player, so I added support
602
+ for it since copy/pasting may be a bit simpler that way.
603
+
604
+ The special key called **:this_file** should be the file that you
605
+ wish to cut. The absolute path should be given here; for my home
606
+ system I also use some fake-macros, such as TALES_FROM_THE_CRYPT/
607
+ to denote where tales from the crypt may reside (and other files).
608
+ This allows me to more easily make use of my local file system.
609
+
610
+ The key **:to** refers to the end position, that is, when to make
611
+ the cut.
612
+
613
+ The ideal scenario for this method is to simply cut from a start
614
+ position to an end position - in other words, to make an existing
615
+ video file shorter.
616
+
617
+ Do note that another class, called CutAudio, also exists as part of
618
+ the multimedia_paradise project. This is partially due to legacy
619
+ reasons; and partially due to CutAudio being primarily used for
620
+ .mp3 files, and for interactive use. One day the functionality
621
+ may be re-used, but for the time being I will keep it separate (less
622
+ work for now).
623
+
624
+ If you rather want a simple API, where you input only two Strings
625
+ usually (as parameters), then you could use:
626
+
627
+ MultimediaParadise.video_duration(of_this_file, '00:30:00-00:35:00')
628
+
629
+ The first argument would be the file that you wish to cut; and
630
+ the second is the duration, so two Strings in total. Interally this
631
+ will be passed to the method **MultimediaParadise.cut_from_to()**
632
+ anyway, so you could even use a Hash instead - but the primary use
633
+ case for that method is to allow for a simpler API. Use whatever
634
+ you prefer.
635
+
636
+ ## Resizing a video
637
+
638
+ **ffmpeg** makes it easy to resize a video.
639
+
640
+ For example, say that you wish to re-scale an existing video
641
+ to the same ratio, but with fewer pixels, like 640. You could
642
+ use the following commandline invocation, with the **-vf**
643
+ flag, for this task:
644
+
645
+ ffmpeg -i input.mp4 -vf scale=640:-1 output.mp4
646
+
647
+ In this case, output.mp4 will have 640 pixels in width.
648
+
649
+ The strange -1 is simply a way to tell ffmpeg that the
650
+ same aspect ratio should be kept. That way ffmpeg will
651
+ calculate which ratio value should be used, in order
652
+ to retain the original width:height relation. You can
653
+ sometimes see that people use the wrong aspect ratio,
654
+ and then their video may look distorted.
655
+
656
+ MultimediaParadise also supports this via:
657
+
658
+ MultimediaParadise.scale_this_video()
659
+ MultimediaParadise.resize_this_vide()
660
+
661
+ The first argument is the path to the local input-file,
662
+ such as **input.mp4*.
663
+
664
+ After that a Hash can be used, where **height** and **width**
665
+ can be given.
666
+
667
+ MultimediaParadise.scale_this_video('input.mp4', height: 320, width: 220)
668
+
669
+ The argument for :width can be omitted, in which case -1 will be used
670
+ as default:
671
+
672
+ MultimediaParadise.scale_this_video('input.mp4', height: 320)
673
+
674
+ Would be the same as:
675
+
676
+ MultimediaParadise.scale_this_video('input.mp4', height: 320, height: -1)
677
+
678
+ The value for height: can be ignored too, in which case it will default
679
+ to 640 - but this default value may change one day in the future, so it
680
+ may be better to specify at the least one value here. But, ultimately,
681
+ if you don't care, this could also work:
682
+
683
+ MultimediaParadise.scale_this_video('input.mp4')
684
+
685
+ We may even omit the first argument in the future, one day, if we
686
+ assign a default file on the toplevel - but for the time being
687
+ (**September 2019**), the API is how it is and requires **at the
688
+ least one argument**.
689
+
690
+ ## Creating a video out of an audio file, such as a .mp3 file
691
+
692
+ Via the API **MultimediaParadise.create_video_from_this_audio()**
693
+ you can "create" a video, from an audio file, such as a .mp3 file.
694
+
695
+ This requires a static image, which is the **second argument** to
696
+ that method.
697
+
698
+ Why did I add this method? I needed a way to upload .mp3 files
699
+ to a remote website but they had a **filter** removing .mp3 files;
700
+ they allowed for .mp4 files, so I converted it into a .mp4
701
+ file and that works. That is strange, since you can always
702
+ use **ffmpeg** to extract the .mp3 audio again - so I dont
703
+ understand the filter that prevents .mp3 upload but allows
704
+ .mp4 upload ...
705
+
706
+ Quite odd if you ask me.
707
+
708
+ **:\\**
709
+
710
+ **:/**
711
+
712
+ Anyway - here an example for the official API for this,
713
+ from within ruby:
714
+
715
+ this_audio_file = 'foobar.mp3'
716
+ this_image_file = '/FORENSIC_CAT.jpg'
717
+ MultimediaParadise.create_video_from_this_audio(this_audio_file, this_image_file)
718
+
719
+ ## MovieSearcher
720
+
721
+ class MovieSearcher can be used to look up information about a
722
+ movie from http://www.omdbapi.com, if you have an API key.
723
+
724
+ The code written for this class is not great, but if all you
725
+ need is some quick commandline information then this class
726
+ could be used. It can be found at
727
+ **multimedia_paradise/video/movie_searcher.rb**.
728
+
729
+ Since as of 02.01.2020, an executable is now distributed
730
+ as well, called **movie_searcher** (under the **bin** subdirectory
731
+ of this gem).
732
+
733
+ I have aliased this executable to **videorating**, and then simply
734
+ do this on the commandline:
735
+
736
+ videorating tremors
737
+
738
+ You may need an API key called **OMDBAPI_API_KEY**. I recommend
739
+ you to set this; class MovieSearch will then try to pick it up
740
+ when it was set (see the ruby code for this).
741
+
742
+ ## Deshaking videos
743
+
744
+ Ffmpeg has support for deshaking videos through a filter:
745
+
746
+ https://ffmpeg.org/ffmpeg-filters.html#deshake
747
+
748
+ The deshake-filter from ffmpeg helps remove camera shake from
749
+ hand-holding a camera.
750
+
751
+ The API for multimedia_paradise is the following:
752
+
753
+ MultimediaParadise.deshake(input_files_go_here)
754
+ MultimediaParadise.deshake('foobar.mp4')
755
+
756
+ ## Missing video files
757
+
758
+ Via:
759
+
760
+ mpa --missing-videos?
761
+
762
+ I can determine which video files are missing locally.
763
+
764
+ This is evidently catered to my own use case, and a big .yml
765
+ file that I maintain. You may have to create your own .yml
766
+ file here if you wish to make use of this functionality.
767
+
768
+ ## class ConvertAudioToVideoWithImage
769
+
770
+ **class ConvertAudioToVideoWithImage** allows you to "attach"
771
+ a static image file to an audio file, such as a <b>.mp3</b>
772
+ file.
773
+
774
+ This functionality depends on **ffmpeg**, so you need to
775
+ have ffmpeg available in order to make use of this class.
776
+
777
+ Two arguments are necessary to class ConvertAudioToVideoWithImage:
778
+
779
+ (1) first, the audio-file
780
+ (2) second, the image file that you wish to use
781
+
782
+ You can also use the following toplevel-method:
783
+
784
+ MultimediaParadise.to_avi_with_this_image()
785
+
786
+ with the same parameter pattern.
787
+
788
+ To give you a specific example - say that you have your .mp3
789
+ file at:
790
+
791
+ /Depot/j/foobar.mp3
792
+
793
+ And your image at:
794
+
795
+ /Depot/Images/foobar.png
796
+
797
+ Then the proper way to use the **toplevel-method** would be:
798
+
799
+ MultimediaParadise.to_avi_with_this_image('/Depot/j/foobar.mp3','/Depot/Images/foobar.png')
800
+
801
+ It does not have to be an **.avi** file though. You can also
802
+ use a .mp4 file via:
803
+
804
+ MultimediaParadise.to_mp4_with_this_image('foo.mp3','bar.png')
805
+
806
+ The latter method can also be used from the commandline via:
807
+
808
+ convert_audio_to_mp4video_with_image a.mp3 b.png
809
+
810
+ Remember that the audio file comes first, and the image file
811
+ comes last.
812
+
813
+ ## Removing the last second of an audio file
814
+
815
+ If you just need to quickly chop off the last 1 second from
816
+ an audio file then you can use this API:
817
+
818
+ MultimediaParadise::RemoveLastSecond.new(ARGV)
819
+ MultimediaParadise::RemoveLastSecond.new('foobar.mp3')
820
+
821
+ ## Encoding a video via MultimediaParadise
822
+
823
+ You can use the toplevel method called **MultimediaParadise.encode_this_video()**
824
+ to encode a video.
825
+
826
+ By default CRF will be used, which is the **Constant Rate Factor**.
827
+
828
+ Support for two-pass encoding has not been added to MultimediParadise,
829
+ but you can read up on ffmpeg how to do this:
830
+
831
+ https://trac.ffmpeg.org/wiki/Encode/H.264
832
+
833
+ Example:
834
+
835
+ require 'multimedia_paradise/toplevel_methods/encode_this_video.rb'
836
+ MultimediaParadise.encode_this_video('foobar.avi')
837
+
838
+ The default output for this will be .mkv, which is the matroska container.
839
+ (Currently that method in MultimediaParadise does not allow for
840
+ another output format, in **June 2020**; but this may be changed in the
841
+ future in another release of this project.)
842
+
843
+ ## MultimediaParadise.set_player_in_use()
844
+
845
+ The toplevel method **MultimediaParadise.set_player_in_use()** can
846
+ be used to set the main multimedia player (audio + video) in use
847
+ for the MultimediaProject. Normally I set this to **mplayer** or
848
+ **mpv**, but **vlc** or any other player could also be used here.
849
+
850
+ You can also quickly set to use **mpv** since as of the 30th
851
+ June 2020.
852
+
853
+ Usage example for permanently setting this:
854
+
855
+ multimedia_paradise --use-mpv
856
+
857
+ This will modify the content of a .yml file.
858
+
859
+ ## The file video_collection.yml
860
+
861
+ The file video_collection.yml, which is distributed by this
862
+ project, can be used to denote different videos files.
863
+
864
+ This is catered to my own use case, but you can adapt this
865
+ file to your own use case.
866
+
867
+ I use the file to automatically handle local videos, such as batch-renaming
868
+ or ensuring that everything is correct, and so on.
869
+
870
+ To determine the default (assumed) location, try this
871
+ method:
872
+
873
+ MultimediaParadise.file_video_collection
874
+
875
+ ## Working with subtitles
876
+
877
+ You can embed subtitles into a video directly. This subsection
878
+ explains how this can be done.
879
+
880
+ Embedding subtitles (text files such as .srt files) into a video
881
+ file is trivial with ffmpeg. The multimedia_paradise project
882
+ supports this as well, via the following toplevel API:
883
+
884
+ require 'multimedia_paradise/toplevel_methods/subtitles.rb'
885
+ MultimediaParadise.embed_this_subtitle_onto_that_video('foo.srt','bar.avi')
886
+
887
+ If you wish to remove a subtitle from a video file, try this:
888
+
889
+ MultimediaParadise.remove_subtitles_from_this_video_file('foobar.mp4')
890
+
891
+ Since as of October 2020, a file called **bin/remove_subtitles**
892
+ is made available as well, for commandline usage.
893
+
894
+ ## Additional documentation and information
895
+
896
+ In **October 2020** I decided to publish all my collected local video
897
+ and audio related content, which is made available through
898
+ oldschool .cgi files. To make this even more complicated, most
899
+ of these files are written in german so these have only a limited
900
+ use for most people. Still, I think some of the information
901
+ contained therein may be useful for other people, which is why
902
+ I will publish this slowly over the coming months. Furthermore,
903
+ some yaml-files are part of this, and publishing yaml files is
904
+ useful, as it is decoupled from the programming language
905
+ (in this case **ruby**).
906
+
907
+ ## Changing the audio codec of a video file via FFMpeg
908
+
909
+ If you want to change the audio codec in a given video file, say,
910
+ **foobar.avi**, then you can use this API:
911
+
912
+ MultimediaParadise.use_lame_codec('foobar.avi')
913
+
914
+ This essentially just combines **-vcodec copy -acodec libmp3lame**
915
+ but I wanted to have a simpler **top-level API** in ruby for this
916
+ too, so this method was added.
917
+
918
+ ## Playing a random (video or audio) file
919
+
920
+ <b>class MultimediaParadise::PlayRandomFile</b> can play a
921
+ random multimedia file. Since this will select a file
922
+ randomly, you can only pass in a directory for now - although
923
+ passing in an Array may also make sense, so perhaps this
924
+ class will be extended at a later time.
925
+
926
+ ## Copying a random video file
927
+
928
+ If you ever need to copy a random video file to the current
929
+ working directory then the following class may be of help
930
+ here:
931
+
932
+ require 'multimedia_paradise/video/copy_random_video.rb'
933
+ MultimediaParadise::CopyRandomVideo.new(ARGV)
934
+
935
+ Unfortunately this is currently hardcoded to my own home
936
+ setup. In the future (past January 2021) I may make this
937
+ more flexible, but it was mostly a "throwaway" script,
938
+ so I just moved on after having written it.
939
+
940
+ ## Bugs in the MultimediaParadise project
941
+
942
+ Bugs are annoying - let's get rid of them!
943
+
944
+ If you run into a bug, or a usability problem, feel
945
+ free to report it. Email should suffice for now; at
946
+ some point I will add github issue trackers again,
947
+ but I am not really using git, so this makes this
948
+ a bit awkward. :)
949
+
950
+ If you can, please provide information how to reproduce
951
+ a given bug. The easier it is to reproduce it, the
952
+ easier it should be to fix it.
953
+
954
+ ## Autogenerate music
955
+
956
+ I will expand this subsection in the coming months and years. The goal
957
+ is to be able to autogenerate at the least some music. I am not
958
+ interested in perfect concertos, but some simple beats that could
959
+ be combined.
960
+
961
+ ## Setting the title metadata of a .mp3 file or any other multimedia-related file
962
+
963
+ Thanks to ffmpeg we can easily modify the metadata entry of a .mp3
964
+ file.
965
+
966
+ MultimediaParadise supports this too, via the following API:
967
+
968
+ MultimediaParadise.set_title_of(this_audio_file, this_title)
969
+
970
+ So, the first argument should be **the local path to the multimedia
971
+ file, such as a .mp3 file**; and the second argument should be the
972
+ title that this file should have. I use this for batch-setting
973
+ the title - and a file called **bin/auto_title** exists that
974
+ does this from the commandline as well.
975
+
976
+ In plain ffmpeg command, it would look like this:
977
+
978
+ ffmpeg -i input.mp4 -metadata title="The video title" -c copy output.mp4
979
+
980
+ The title comes into the title="" entry there.
981
+
982
+ For .mp4 files, but possibly also .mp4 files, you could use the following
983
+ meta-data tags:
984
+
985
+ - title
986
+ - author
987
+ - album_artist
988
+ - album
989
+ - grouping
990
+ - composer
991
+ - year
992
+ - track
993
+ - comment
994
+ - genre
995
+ - copyright
996
+ - description
997
+ - synopsis
998
+ - show
999
+ - episode_id
1000
+ - network
1001
+ - lyrics
1002
+
1003
+ ## Obtaining an image from a video file via ffmpeg
1004
+
1005
+ You can use this commandline variant to obtain one image from
1006
+ a video file. Via **-ss** you can specify the start position.
1007
+
1008
+ Usage example:
1009
+
1010
+ ffmpeg -i input.mp4 -vframes 1 -an -s 320x180 -y -ss 12 output.jpg
1011
+
1012
+ The multimedia_paradise gem makes this possible via this API:
1013
+
1014
+ MultimediaParadise.return_image_from_this_video_file(
1015
+ 'input.mp4',
1016
+ starting_position = 12, # in n seconds
1017
+ width_and_height_for_the_image = '480x270'
1018
+ )
1019
+
1020
+ The path to the local video file should come as the first argument
1021
+ to this method.
1022
+
1023
+ ## The sinatra interface of the MultimediaParadise project
1024
+
1025
+ First install sinatra:
1026
+
1027
+ gem install sinatra # or use --user-install
1028
+
1029
+ Next you should be able to start it, either via **MultimediaParadise.start_sinatra**
1030
+ or from the commandline via:
1031
+
1032
+ multimedia_paradise --sinatra
1033
+
1034
+ You should then be presented with the sinatra-interface.
1035
+
1036
+ For example, to determine how many local videos are available, use
1037
+ n_local_videos, as in:
1038
+
1039
+ http://localhost:5580/n_local_videos
1040
+
1041
+ This is also available via the index, so you just have to click on
1042
+ it via the mouse button.
1043
+
1044
+ You can view all registered video files, aka their respective
1045
+ names, via:
1046
+
1047
+ http://localhost:5580/available_video_files
1048
+
1049
+ You can also directly play video files, if they are available (at
1050
+ the least on my home setup) via:
1051
+
1052
+ http://localhost:5580/027
1053
+
1054
+ Or just the name. This requires that the base directory where
1055
+ the video file resides, is added to the sinatra application.
1056
+ And, of course, that the video file also exists at that path.
1057
+ If it does not work on your system, make sure that the
1058
+ correct directory is passed in, and that the video file
1059
+ exists locally; have a look at the sinatra-specific
1060
+ code in **multimedia_paradise/sinatra/**. The default is
1061
+ for my home system so you may have to change a very few
1062
+ lines.
1063
+
1064
+ You can also pass the name of the video file directly and if it
1065
+ exists in the specified directory it will be played.
1066
+
1067
+ I tested this on windows as well, and it works there - at the
1068
+ least for .mp4 files. I could not get .avi files to work yet,
1069
+ neither on windows nor on linux. I am not entirely certain
1070
+ as to why, but perhaps it may be time to ditch .avi files
1071
+ altogether, in favour of .mp4.
1072
+
1073
+ I also intend to add a play/ API just to keep this a bit
1074
+ separate and visually nicer.
1075
+
1076
+ Unfortunately I have been hitting some problems with sinatra,
1077
+ namely that I have no idea what is going on "behind the scenes".
1078
+ I'll have to re-evaluate this at a later time - mostly trying to
1079
+ find a replacement that is more debug-friendly than sinatra,
1080
+ without being as bloated as ruby on rails.
1081
+
1082
+ In June 2022 I tested this on windows, such as via an URL
1083
+ to a local video file like:
1084
+
1085
+ http://localhost:5580/035_Back_to_the_Future.mp4
1086
+
1087
+ And it worked! \o/
1088
+
1089
+ The .mp4 file was playing in the browser. I guess this will
1090
+ favour the .mp4 file format versus .mkv or .avi, simply
1091
+ because it gives us one more option to play video files.
1092
+ I did get .mkv to work in the browser, though, so perhaps
1093
+ only .avi is the one that will have to be deprecated.
1094
+
1095
+ It goes slower than on Linux, though, so Linux is really
1096
+ the better operating system, in my opinion.
1097
+
1098
+ ## Lyrics of songs
1099
+
1100
+ This subsection is just a little reminder for myself.
1101
+
1102
+ I searched for translations of different lyrics on the www. However
1103
+ had, many of the translations are clearly wrong, where the words are
1104
+ incorrect. In theory this may be because whoever made the translation
1105
+ manually simply misheard the word(s) - but often the words are so
1106
+ different that this can not be explained by a genuine mistake,
1107
+ in my opinion. I think many of these translations are **deliberately**
1108
+ incorrect, simply because the words are too different. This problem
1109
+ is then amplified by different websites copy/pasting the same
1110
+ error.
1111
+
1112
+ I give you a specific example.
1113
+
1114
+ During the eurodance era, there was one interesting rapper
1115
+ in the group **Sonic Surfers**, with the song called
1116
+ **Don't give it up**.
1117
+
1118
+ One passage is 'officially' this:
1119
+
1120
+ Tap into my brain and just channelin'
1121
+ Let's get high on bass and trebelin'
1122
+
1123
+ However had, I listened to this part about ten times now and
1124
+ in my opinion the text is the following:
1125
+
1126
+ Tap into my brain and just channelin'
1127
+ Let's get high on base and adrenaline
1128
+
1129
+ I am almost 100% certain that he said "base" and "adrenaline".
1130
+ It also makes more sense - adrenaline is more logical than
1131
+ trebeling, whatever that should even be. So why was the translation
1132
+ that is available on the www different? Yes, it may be a sloppy
1133
+ mistake, I understand that, but ... to mistake two words that
1134
+ are quite clearly different? And that is not the only example.
1135
+
1136
+ In the same text of the song you have this passage:
1137
+
1138
+ If anybody should be trippin' as you do
1139
+ Dance into the trance on my little kavoodoo
1140
+
1141
+ But my own translation is this:
1142
+
1143
+ If anybody should be trippin' as you do
1144
+ Dance into the trance on my lyrical voodoo
1145
+
1146
+ Again - I could be wrong, but ... not sure. Lyrical
1147
+ voodoo makes more sense than does "little kavoodoo" too.
1148
+
1149
+ Anyway. You can find many similar examples in different songs. I
1150
+ do not think these are ALL accidents; I think the translations are,
1151
+ at the least to some extent, deliberately incorrect. You could
1152
+ reason - or assume - that this came automated by scripts/robots,
1153
+ but the errors seem so subtly incorrect that I have a hard time
1154
+ imagining this did not come by some random underpaid person in
1155
+ India or what not, working for a low wage ... so there may be a
1156
+ non-deliberate accident explanation, but still. It is **clearly
1157
+ not correct either way how you look at it**, for whatever the
1158
+ underlying reason for this may be. (Since as of 2023 I have
1159
+ amended my opinion a little bit - this could actually have come
1160
+ from some AI-specific tool, such as ChatGPT or what not. I am
1161
+ no longer certain this came from a human, despite the seemingly
1162
+ non-randomness of the editing. This could be explained if a
1163
+ script was not making changes ALL of the time but included some
1164
+ more context from elsewhere.)
1165
+
1166
+ Evidently this is fairly pointless for other people to know, but since
1167
+ I actually want to understand the lyrics of good songs I thought
1168
+ I should note this down, for future reference. My larger theory is
1169
+ that many - or most - of these translations were created not by
1170
+ human beings but by a script (perhaps not the above example, but
1171
+ many others). And that script was, possibly, altered to include
1172
+ deliberately incorrect words near the end. That would explain the
1173
+ pattern I could see above, where the first sentence is correct, the
1174
+ second sentence becomes incorrect towards the end. It could just
1175
+ be a human too, though - not possible to distinguish this.
1176
+
1177
+ (Of course a human being could also do this, e. g. if paid to
1178
+ do this and then consistently apply that pattern, or indeed
1179
+ doing genuine mistakes. It's not possible to easily distinguish
1180
+ between a script, or human beings that work consistently in
1181
+ doing incorrect translations. But a script runs for virtually
1182
+ free, whereas human beings cost money, so I assume the more
1183
+ likely explanation is that this is done by one, or several,
1184
+ script(s). Would be interesting to find out WHO is doing these
1185
+ translations on different websites. Some evidently only
1186
+ copy/paste, because you can find the exact same error in
1187
+ the "translated" websites as well.)
1188
+
1189
+ I do not have enough statistical data to verify either way, but I
1190
+ am quite suspicious about what is presented to me nowadays via
1191
+ Google in general - I happily admit that I no longer trust Google, so
1192
+ I will simply assume that many of these translations (but not all)
1193
+ did not come from human beings, but from software instead. You
1194
+ can also find websites that aggregate other resources, and the
1195
+ randomly munch it together in ways that makes no real sense. So
1196
+ much fake stuff going on these days ...
1197
+
1198
+ ## Adding silence to an audio file
1199
+
1200
+ If you want to append 5 seconds of **silence** to a song, you can
1201
+ do so via **sox**, and the following API in the MultimediaParadise
1202
+ toplevel namespace:
1203
+
1204
+ MultimediaParadise.append_silence_to_this_song(5, 'ack.mp3')
1205
+
1206
+ (The file size of the new song will be fairly large, though. I
1207
+ am not certain as to why that is the case. Seems awkward that
1208
+ silence leads to a massively increased file size ... anyone knows
1209
+ how to do that via ffmpeg?)
1210
+
1211
+ ## CutMultimedia - a merger of CutAudio and CutVideo
1212
+
1213
+ Many years ago I had a class called **CutAudio**. I even received
1214
+ an email concerning this class (which was made available as a
1215
+ standalone .gem on rubygems.org, back then), from a user who reported
1216
+ several bugs with it - and a lack of documentation. All of which was
1217
+ correct back then. :-)
1218
+
1219
+ In **February 2021** I finally started to rewrite the important
1220
+ parts of the old class called **CutAudio** into **CutMultimedia**,
1221
+ while also adding **more documentation** to it. This is presently
1222
+ still an ongoing endeavour, so ... stay-tuned in this regard!
1223
+
1224
+ Another goal for this rewrite was to add **ruby-gtk3 bindings** to
1225
+ it from the get go. That way users who do not like the commandline
1226
+ are able to use this class as well, if they have ruby-gtk3
1227
+ available. The primary focus, nonetheless, is on the commandline
1228
+ use, though, and not everything that is available on the commandline
1229
+ is available via the GUI. The GUI mostly only captures the
1230
+ essential parts, whereas the commandline exposes more functionality
1231
+ that is less commonly required.
1232
+
1233
+ The idea behind class **CutMultimedia** is that no matter whether you use
1234
+ a video file or an audio file as input to this class, to allow you to
1235
+ easily and quickly <b>cut</b> this audio file (or video file), and
1236
+ **re-join** these new audio files easily as well into a single file.
1237
+ So it is not only cutting alone; it also means to make use of
1238
+ re-joining. The end product is then a new file, such as a new .mp3
1239
+ file. The interactive part that is made available via the menu()
1240
+ method exists primarily to facilitate that goal: to cut an
1241
+ existing .mp3 file and rejoin the desired segments into a new
1242
+ .mp3 file.
1243
+
1244
+ The name for the class is now **CutMultimedia**, but a backwards
1245
+ alias exists, called **CutAudio**. For consistency reasons, **CutVideo**
1246
+ also exists. I recommend to use the name **CutMultimedia** directly,
1247
+ though - that name should be more 'durable' than the other two
1248
+ names.
1249
+
1250
+ You can find the code for this class here, in the following
1251
+ subdirectory:
1252
+
1253
+ require 'multimedia_paradise/multimedia/cut_multimedia/*.rb'
1254
+
1255
+ The class can be invoked by either of the following executables,
1256
+ residing under the <b>bin/</b> hierarchy:
1257
+
1258
+ bin/cut_audio
1259
+ bin/cut_video
1260
+ bin/cut_multimedia # this one is probably the best variant
1261
+
1262
+ Simply have a look at the file content if you have a hard
1263
+ time finding it on your file system; something changed in
1264
+ rubygems so I don't know where files are placed anymore,
1265
+ but these bin/ files are part of the .gem, so simply
1266
+ extract the gem and have a look around.
1267
+
1268
+ As **first argument** to this class you should <b<provide the
1269
+ path to the audio or video file</b> that you wish to modify.
1270
+
1271
+ For example, if you have a file available at the location
1272
+ **/tmp/foobar.mp3** then you could invoke **cut_audio**
1273
+ like so:
1274
+
1275
+ bin/cut_audio /tmp/foobar.mp3
1276
+ cut_audio /tmp/foobar.mp3
1277
+ caudio /tmp/foobar.mp3 # I actually use an alias called 'caudio'; faster and easier for me to type.
1278
+
1279
+ Or use **cut_multimedia** as a name instead - that is equivalent
1280
+ since as of **February 2021**.
1281
+
1282
+ You can avoid the leading bin/ part if the file at hand is
1283
+ in your PATH variable. Or if you set an alias, anyway.
1284
+
1285
+ (As said Ialiased it to "caudio", as that is my mnemonic
1286
+ for "cut-audio".)
1287
+
1288
+ When you apply the above command, on the commandline, you will
1289
+ enter the **interactive menu** interface (if that file was
1290
+ found). This interface allows you to do certain actions that
1291
+ can be helpful in regards to cutting audio or video files.
1292
+
1293
+ For example, specifying start and end position of the
1294
+ **cutting job**, which is one of the most commonly commands
1295
+ I use. See some examples for this a bit below.
1296
+
1297
+ You can also ask for "help" via:
1298
+
1299
+ help
1300
+
1301
+ while you are in the interactive mode.
1302
+
1303
+ You can use the ruby-gtk3 interface, which is under
1304
+ **multimedia_paradise/gui/gtk3/cut_multimedia/**.
1305
+
1306
+ You can designate **start** and **stop** positions when in
1307
+ **interactive mode** of class CutMultimedia. You can do so
1308
+ via prefixing "s" and suffixing "e", such as in the
1309
+ following way:
1310
+
1311
+ s10 # start at 10 seconds
1312
+ e20 # end at 20 seconds
1313
+
1314
+ This would mean to "start at 10 seconds" and "end at 20 seconds".
1315
+ So we will here **cut out the intermediate 10 seconds**
1316
+ between these two points.
1317
+
1318
+ If you want the commands to be more verbose, try these longer
1319
+ variants instead:
1320
+
1321
+ start10
1322
+ end20
1323
+
1324
+ But I prefer "s" and "e" - less to type.
1325
+
1326
+ There is some support for specifying both start and end positions
1327
+ in one go. For example, the above commands shown so far require
1328
+ two lines to be used, e. g. first s10 and then e20. You can
1329
+ simplify this to the following one-liner instead:
1330
+
1331
+ 10-20
1332
+ 10 - 20 # this is also possible, if you want it more spaced out
1333
+
1334
+ That way you can skip using the "s" and "e" altogether and it
1335
+ should work just fine. If it does not, it is most likely a
1336
+ bug - feel free to send an email to point out a bug, or
1337
+ something missing in regards to the documentation and it
1338
+ will be addressed eventually.
1339
+
1340
+ Via "play" you can play the audio file at hand; I recommend having
1341
+ installed **mplayer** or **mpv** for this task. That way you can
1342
+ find out **where** you may wish to cut in the first place. I use
1343
+ this quickly to determine the exact positions, on the commandline,
1344
+ and then continue to define start and end positions.
1345
+
1346
+ Once you have all your start and end positions defined, you can
1347
+ run the following command to **commit**:
1348
+
1349
+ cut
1350
+
1351
+ This will cut out the selected subsection; in this case the part
1352
+ from 10 seconds to 20 seconds. You will then have a new .mp3
1353
+ file that should be about 10 seconds long (ffmpeg does not
1354
+ seem to cut at 100% precision all the time; recently it created
1355
+ a file with a duration of 10.03 seconds rather than 10.00
1356
+ seconds. I do not know why, so I can not explain this
1357
+ behaviour.)
1358
+
1359
+ The **number** in use there specifies how many seconds are to be used.
1360
+ This can sometimes be a bit difficult to calculate in your head
1361
+ e. g. how many seconds do **83 minutes** entail to. How many of
1362
+ you can quickly calculate this accurately in your head? I
1363
+ struggle there.
1364
+
1365
+ So, a 'pseudo-calculator' can be used and queried from within
1366
+ class **CutMultimedia**.
1367
+
1368
+ For example, if you input the following:
1369
+
1370
+ 6*60
1371
+
1372
+ Then this would quickly show you that the result of this is
1373
+ 360 seconds (the input meant **6 minutes**, if you think about
1374
+ it - aka 6 * 60 seconds, as one minute has 60 seconds).
1375
+
1376
+ There are many more options available, so have a look at the
1377
+ "help" section there. Keep in mind that <b>CutMultimedia</b> is
1378
+ a bit complicated to use sometimes, and also has had a very
1379
+ few bugs as well. On the other hand, if you focus on the three
1380
+ main actions (start, end, cut) then this is really quite simply
1381
+ to use. You'll get the hang of it quickly.
1382
+
1383
+ Take note that the **ruby-gtk3 bindings** to class CutMultimedia
1384
+ are not perfect, and they are not complete, either. I may improve
1385
+ on them in the future, but for now they have to suffice. (My
1386
+ main goal is to actually clone the functionality of
1387
+ **mp3directcut**, but I don't know how to run a visualize-function
1388
+ so ... that's on my todo list.)
1389
+
1390
+ Note that you can start the ruby-gtk3 bindings from the
1391
+ interactive menu via:
1392
+
1393
+ gui
1394
+
1395
+ In **October 2021** code was added to use this in a scripted
1396
+ fashion. So, rather than define the start and end positions
1397
+ interactively, you can now input them into a text file
1398
+ instead.
1399
+
1400
+ The format of this text file should look like this:
1401
+
1402
+ start 2
1403
+ end 4
1404
+ start 6
1405
+ end 8
1406
+
1407
+ s 10.5
1408
+ e 12.5
1409
+
1410
+ So, alternating between start_position and end_position.
1411
+ That's it.
1412
+
1413
+ You can use "start" or "s", or "end" or "e", respectively.
1414
+ But either of which is mandatory; omitting both s and e
1415
+ is not possible.
1416
+
1417
+ Furthermore you need to use a "clean" workspace, aka only
1418
+ the file that you wish to modify, such as **foobar.mp3**
1419
+ in the given directory.
1420
+
1421
+ The code for this functionality is available in the
1422
+ following API:
1423
+
1424
+ MultimediaParadise::CutMultimedia.evaluate_from_this_file()
1425
+
1426
+ Pass, as <b>argument to it</b>, the file that contains these
1427
+ short and end positions, e. g. the text file that you will
1428
+ use. The code will then <b>automatically</b> pick up the
1429
+ first .mp3 file that it can find in the current directory,
1430
+ so again, use a clean workspace for this step.
1431
+
1432
+ Then it will do the specified actions and merge the newly
1433
+ created files back in. (There is also an additional step to
1434
+ convert to .wav and back to .mp3. The reason for this is that
1435
+ somehow ffmpeg's concat feature does not fix the broken
1436
+ headers. I don't know how else to fix this other than
1437
+ re-encoding. If someone else has a better solution I
1438
+ will be happy to hear it.)
1439
+
1440
+ If the file was generated (aka merged) then all other files
1441
+ used in the process will be removed. So if all goes well,
1442
+ you will have +1 file in that directory: the cutted file.
1443
+
1444
+ Note that while CutMultimedia, originally called CutAudio,
1445
+ was started to cut .mp3 files, you can also modify other
1446
+ files with it too, such as merging/cutting .waf files,
1447
+ .ogg files, .aac files, .aiff files and so forth. The only
1448
+ requirement is that ffmpeg can handle these files.
1449
+
1450
+ In October 2023 class CutMultimedia was improved a bit. It
1451
+ is now possible to only specify an end position, via:
1452
+
1453
+ -00:28:49
1454
+
1455
+ This will (automatically) designate the start position at 0.
1456
+
1457
+ ## Overlaying two audio songs
1458
+
1459
+ Use:
1460
+
1461
+ MultimediaParadise.overlay_two_audio_files()
1462
+ MultimediaParadise.overlay_two_audio_files('foo.mp3','bar.mp3')
1463
+
1464
+ This depends on **sox**. It is possible to do so via ffmpeg but the
1465
+ syntax is very complex, so I opted for sox for now. In the future
1466
+ this may be improved, but for now this has to suffice.
1467
+
1468
+ ## mp3 tags
1469
+
1470
+ This short subsection contains just a bit of information concerning
1471
+ mp3 ID tags. I needed this because I added a ruby-gtk3 based
1472
+ mp3-id-tagger some time ago.
1473
+
1474
+ **ID3v1 tags** have a 30-character limit. Thus, it is better to
1475
+ avoid ID3v1 and just use ID3v2.
1476
+
1477
+ Software such as **Mp3tag** can show whether the .mp3 file uses
1478
+ ID3v1 or ID3v2.
1479
+
1480
+ **ID3v2 tags** are also limited (nothing is infinite here), but
1481
+ the limit is at either 255, 32000, or 64000 some such. Even
1482
+ 255 already is more than enough for most text, in my opinion.
1483
+
1484
+ ## MultimediaParadise::ImdbRating
1485
+
1486
+ class **MultimediaParadise::ImdbRating** can be used to display
1487
+ the rating for a movie on the commandline, if it is registered
1488
+ as part of IMDB.
1489
+
1490
+ ## MultimediaParadise::Multimedia::VideoDownloader
1491
+
1492
+ class **MultimediaParadise::Multimedia::VideoDownloader** was
1493
+ added in December 2021. The idea is that whenever we want to
1494
+ download some remote video, this class should do that task
1495
+ for us. It has been designed to be re-usable from the get
1496
+ go.
1497
+
1498
+ Downloaded video files go into a directory such as this:
1499
+
1500
+ /home/Temp/multimedia_paradise/downloaded_videos/
1501
+
1502
+ This may be different on your system. Furthermore, old
1503
+ videos are NOT deleted, so this directory may become
1504
+ very big. Other classes that may merge all video files
1505
+ into one video file will simply pick up whatever is
1506
+ in that directory, so make sure to keep that directory
1507
+ clean before calling other classes. At a future point
1508
+ in time this behaviour may change, and become more
1509
+ user-friendly - but for now, this is documented here
1510
+ so that people are aware of it, until that behaviour
1511
+ is changed (simplified in particular).
1512
+
1513
+ ## AudioPlayer
1514
+
1515
+ This class is just a thin "wrapper" over **mplayer** or
1516
+ **mpv** really. It has been created in **early June 2014**.
1517
+
1518
+ The file can be found at
1519
+ **multimedia_paradise/audio/audio_player/audio_player.rb**.
1520
+
1521
+ It was originally created because I needed to play, via
1522
+ the commandline, audio songs in a <b>loop</b> - like a
1523
+ **juke box**. I wanted it to be very simple too, so no
1524
+ ncurses interface to it.
1525
+
1526
+ I also use it to perform wake-up calls in the morning, like
1527
+ an alarm clock.
1528
+
1529
+ There is an **executable** for this, at **bin/audio_player**,
1530
+ which acts as entry point to the code behind it, for
1531
+ <b>class MultimediaParadise::AudioPlayer</b>.
1532
+
1533
+ If you want to **play in a loop**, you can pass the argument
1534
+ "loop" or just "l".
1535
+
1536
+ Since as of the **24th February 2018**, it can also act as a
1537
+ "timer", together with class <b>Roebe::At</b>, which is part
1538
+ of the **roebe** gem. For example, if you want to play
1539
+ random songs at the time **21:35:00**, you can do:
1540
+
1541
+ rsong 21:35:00
1542
+
1543
+ Note that <b>rsong</b> is simply an alias that I use towards
1544
+ <b>bin/audio_player</b>. Without an alias, the above becomes:
1545
+
1546
+ audio_player 21:35:00
1547
+
1548
+ Usually I tend to use <b>mpv</b>, but sometimes I do use
1549
+ mplayer, e. g. when mpv has some problem due to recent
1550
+ API changes. In this case, one can specify to use mplayer
1551
+ on the commandline, via:
1552
+
1553
+ rsong 10:00:00 --use-mplayer
1554
+
1555
+ As already mentioned, mpv or mplayer are the two main
1556
+ audio players (binaries). But there are more alternatives
1557
+ available. For example, the program called **sox**
1558
+ has a binary called **play**. I have had a use case
1559
+ in February 2022 where neither mpv nor mplayer worked,
1560
+ due to a dependent library being broken (a temporary
1561
+ problem). As I was fixing this, I wanted to listen
1562
+ to music still, and added ad-hoc support for sox.
1563
+
1564
+ This can be triggered via:
1565
+
1566
+ rsong --use-sox
1567
+
1568
+ The binary **play** will be used as a result of this
1569
+ commandline flag.
1570
+
1571
+ ## Download videos from Google (actually Youtube)
1572
+
1573
+ The file google_video_downloader.rb can be used to download
1574
+ videos from Google - but we may have to use youtube-dl for
1575
+ this, which is python. This is not ideal since we use ruby :)
1576
+ but I am too lazy to clone the functionality of <b>youtube-dl</b>
1577
+ for now, so this just has to be glue code really. (Glue code
1578
+ is for lazy people and laziness can be a virtue, even if it
1579
+ may not be the best virtue to be had.)
1580
+
1581
+ For anyone who would like to give a replacement in ruby -
1582
+ you probably don't need to replace all of youtube-dl,
1583
+ only the part where we can obtain an URL. The rest can
1584
+ be solved by wget or curl, supposedly; or just ruby via
1585
+ it's open-uri functionality, for instance..
1586
+
1587
+ ## Embedding Youtube Videos
1588
+
1589
+ "Embedding" Youtube Videos is also possible. Note the quotes.
1590
+
1591
+ The code is in the file **multimedia_paradise/video/youtube_embedder.rb**.
1592
+
1593
+ ## Playlists
1594
+
1595
+ The **MultimediaParadise** project can generate **.m3u** files, as long as
1596
+ they are simple, e. g. one entry per line. For the purpose of the document
1597
+ here, we will call such **.m3u** files
1598
+ **playlists**.
1599
+
1600
+ The class responsible for the creation of **.m3u** files - that is
1601
+ **playlist files** - is class <b>MultimediaParadise::CreateM3uPlaylist</b>,
1602
+ residing at the location <b>multimedia_paradise/audio/create_m3u_playlist.rb</b>
1603
+ within the **MultimediaParadise** project.
1604
+
1605
+ The primary objective of this class is to generate that
1606
+ **.m3u** text file. Of course you can do so easily without the
1607
+ project - just do a "ls" and pipe the output it into a file, more
1608
+ or less - but I wanted this functionality specifically within the
1609
+ multimedia_paradise project, so that I can automate the creation
1610
+ of playlists, including batch-uploading to other websites at a
1611
+ later time, such as for youtube and similar remote websites. Thus
1612
+ I wanted to tie the functionality into the multimedia_paradise
1613
+ gem.
1614
+
1615
+ I myself use that class to generate playlists for various different
1616
+ **song types** - be these **eurodance songs**, **trance songs**,
1617
+ **pop songs** and so forth. Once such a .m3u file has been
1618
+ (auto)generated, it could then be used for uploading this file
1619
+ to an external website, as mentioned, such as to **youtube** or
1620
+ other websites that support playlists like that. Of course in order
1621
+ for this to work you may need to provide valid URLs to these
1622
+ individual remote entries somehow. The primary use case for
1623
+ class <b>MultimediaParadise::CreateM3uPlaylist</b> is for
1624
+ **local audio files**, though.
1625
+
1626
+ So, how to use class <b>MultimediaParadise::CreateM3uPlaylist</b>?
1627
+
1628
+ The input to class <b>MultimediaParadise::CreateM3uPlaylist</b>
1629
+ should ideally be a **yaml file** describing your songs (at the
1630
+ least **the path to these songs**), but you could also use the **API**
1631
+ from within Ruby, naturally and thus use a **ruby array** directly
1632
+ that is to be passed to the class; just pass this Array to
1633
+ **.new()**.
1634
+
1635
+ Let's show a simple example for this:
1636
+
1637
+ MultimediaParadise::CreateM3uPlaylist.new(%( /foo/bar.mp3 /bar/foo.mp3 /tmp/dah.mp ))
1638
+
1639
+ You can also use this simpler **toplevel method**, in ruby instead:
1640
+
1641
+ MultimediaParadise.create_m3u_playlist()
1642
+
1643
+ The **first argument** to this method should contain the **dataset**
1644
+ that you will use for the .m3u file that is to be autogenerated.
1645
+ This should be a simple Array.
1646
+
1647
+ You can, naturally, rename the .m3u file after it has been created,
1648
+ since a default name will be used - the <b>generic name</b> used for
1649
+ generation of the file will be <b style="color: royalblue">playlist.m3u</b>.
1650
+
1651
+ For my own custom dataset, e. g. to generate a playlist with decent
1652
+ **tales-from-the-crypt** videos, I can just do:
1653
+
1654
+ playlist --tales-from-the-crypt
1655
+
1656
+ The **MultimediaParadise project** also comes with another class,
1657
+ called **class Playlist**, which has a different task. That
1658
+ **class Playlist** will handle audio-playlists, primarily. For
1659
+ example, it can play audio files at certain positions in
1660
+ the playlist.
1661
+
1662
+ Usage example from the commandline for this:
1663
+
1664
+ playlist 33,44,55
1665
+
1666
+ Would play the songs at position 33, then 44 and then 55. It
1667
+ is thus a very primitive sort of **jukebox**. See
1668
+ **playlist --help** for help options.
1669
+
1670
+ You can change positions in that playlist. To exchange position
1671
+ 95 with position 94, you could use input like this:
1672
+
1673
+ playlist "95 -> 94"
1674
+
1675
+ This would mean to take the song at position 95 and move it
1676
+ to position 94. Conversely the song at position 94 will be
1677
+ moved to 95; this is thus ***an exchange operation***.
1678
+
1679
+ To show the entries of a playlist do:
1680
+
1681
+ playlist --show
1682
+
1683
+ (You can also omit this commandline flag since as of December
1684
+ 2020. This will default to show all entries in the playlist
1685
+ then.)
1686
+
1687
+ Note that by default this is adjusted to my own dataset, which
1688
+ is most likely totally useless to other people. You have to
1689
+ use your own playlist (a .yml file, called **playlist.yml**).
1690
+
1691
+ To see the available music-genres, try:
1692
+
1693
+ playlist --genres
1694
+
1695
+ In February 2022 a new class was added, called
1696
+ **MultimediaParadise::SimulateYoutubePlaylist**. The goal
1697
+ for this class is to "simulate" a playlist that could be
1698
+ used for youtube. It can also automatically create a
1699
+ .m3u list.
1700
+
1701
+ The idea here is that you can build up a playlist without
1702
+ depending on google necessarily. So you can add a bunch
1703
+ of remote URLs to youtube videos into a yaml file and
1704
+ have these work. They will be opened via the browser
1705
+ one after the other. Note that for this to work you
1706
+ have to install the 'open' gem, via "gem install open".
1707
+
1708
+ Note that as of February 2022 the class it not yet finished.
1709
+ It can batch-download the videos from the remote URLs
1710
+ given, but it is not really user-friendly yet. Stay
1711
+ tuned in this regard.
1712
+
1713
+ Normally the environment variable <b>USE_THIS_VIDEO_PLAYER</b>
1714
+ can be used to designate which multimedia player shall play
1715
+ these files. Since as of <b>April 2023</b> it is possible
1716
+ to override this, via <b>--use-mplayer</b>, <b>--use-vlc</b>
1717
+ or <b>--use-mpv</b> specifically. Examples for this functionality
1718
+ follow next:
1719
+
1720
+ playlist 126,127,101 --use-mplayer
1721
+ playlist 126,127,101 --use-mpv
1722
+ playlist 126,127,101 --use-vlc
1723
+
1724
+ ## Watermarking videos
1725
+
1726
+ A <b>watermark</b> is a specific tag to a video. This can be a
1727
+ <b>logo</b> but it can also be used as some kind of (annoying)
1728
+ filter.
1729
+
1730
+ Whatever your use case may be, ffmpeg supports watermarking
1731
+ videos - and multimedia_paradise taps right into that
1732
+ functionality.
1733
+
1734
+ Adding a watermark to a video is possible and quite simple.
1735
+
1736
+ The class that does so, in regards to the MultimediaParadise
1737
+ project, is aptly called <b>Watermark</b> and it allows you
1738
+ to use FFMPEG to embed a watermark video, using the
1739
+ simple <b>MultimediaParadise.watermark()</b> method.
1740
+
1741
+ I rarely need to use this method so it may not be as
1742
+ polished as other parts of the project, though.
1743
+
1744
+ The default use case is to simply call that .rb file and
1745
+ pass a video file to it, such as shown in the following
1746
+ example:
1747
+
1748
+ vwatermark /Depot/Temp/MultimediaProject/foobar.mp4
1749
+
1750
+ (vwatermark is an alias on my system to simplify
1751
+ this. It will call the .rb file directly)
1752
+
1753
+ If you want to use your own image, then you have to pass an
1754
+ additional argument to the method, which should be the path
1755
+ to the image at hand.
1756
+
1757
+ vwatermark /Depot/Temp/MultimediaProject/foobar.mp4 /opt/my_awesome_logo.png
1758
+
1759
+ That's about it!
1760
+
1761
+ ## ffmpeg_merge
1762
+
1763
+ This file, at **bin/ffmpeg_merge**, was added in April 2022
1764
+ to quickly merge multimedia files together, via the
1765
+ commandline.
1766
+
1767
+ ## Shrinking the size of .mp3 files
1768
+
1769
+ If you need a method to process all .mp3 files, via **lame**,
1770
+ then you can use the following method:
1771
+
1772
+ MultimediaParadise.shrink_quality_of_these_mp3_files(Dir['*.mp3'])
1773
+
1774
+ ## Noise in audio files (such as .mp3) and denoising these files (that is remove the noise)
1775
+
1776
+ Say you have some audio recording on the street, and some cars drive
1777
+ by or some birds chirp. This is often not wanted or even distracting.
1778
+
1779
+ So, how about removing that noise part? It is possible, even for
1780
+ simple human beings. One solution is to use **sox** for this
1781
+ task.
1782
+
1783
+ Note that this depends on the quality of the audio and the patterns
1784
+ that can be found in the noise itself, so different audio files
1785
+ will not work equally well. But let's assume a simple audio file
1786
+ and there are repetitive entities (repetitive data) inside of
1787
+ that stream.
1788
+
1789
+ **sox** allows the removal of these repetitive structures via the
1790
+ <b>noiseprof</b> and <b>noisered effects</b> of sox.
1791
+
1792
+ First, work on a test-audio file and let's call it <b>foobar.mp3</b>.
1793
+ Put it into an area where you can work with it.
1794
+
1795
+ Now that this was done, use sox to <b>create a background noise
1796
+ profile</b> from this .mp3 file:
1797
+
1798
+ sox foobar.mp3 -n noiseprof noise.profile
1799
+
1800
+ The next step is to go ahead and <b>remove the noise</b>
1801
+ from the given .mp3 file using this <b>profile</b>:
1802
+
1803
+ sox foobar.mp3 output.mp3 noisered noise.profile 0.21
1804
+
1805
+ These are the commandline instructions. MultimediaParadise
1806
+ has right now (May 2022) the first one built in as a
1807
+ toplevel API. Use it like this:
1808
+
1809
+ MultimediaParadise.create_noise_profile(of_this_mp3_file)
1810
+ MultimediaParadise.create_noise_profile('foobar.mp3') # See the commandline instructions mentioned above.
1811
+
1812
+ ## Deinterlacing a video
1813
+
1814
+ You can deinterlace a video via this API:
1815
+
1816
+ MultimediaParadise.deinterlace_this_video()
1817
+ MultimediaParadise.deinterlace_this_video('foobar.avi')
1818
+
1819
+ ## Converting to the .mp4 format
1820
+
1821
+ In my local video collection I have various <b>.mkv</b> files.
1822
+ These work fine via **mpv**, but if I try to play these on firefox,
1823
+ via the <b>HTML5 tags</b>, then it does not work. One solution is
1824
+ to convert them into .mp4 files; then they may work in the browser
1825
+ as well.
1826
+
1827
+ The multimedia_paradise gem has this enabled via the following
1828
+ toplevel API:
1829
+
1830
+ MultimediaParadise.to_mp4
1831
+ MultimediaParadise.to_mp4('foobar.mkv') # Input the filename here.
1832
+
1833
+ This is essentially the same as issuing the following on the
1834
+ commandline, via <b>ffmpeg</b>:
1835
+
1836
+ ffmpeg -i foobar.mkv -vcodec copy -acodec copy foobar.mp4
1837
+
1838
+ So, not a huge "time saver" as such, as you can just do the above
1839
+ on your own. But I wanted to have this enabled within the
1840
+ multimedia_paradise gem. Furthermore, a file called **bin/to_mp4**
1841
+ exists, to make available this functionality as-is.
1842
+
1843
+ Then the usage example on the commandline would be:
1844
+
1845
+ to_mp4 foobar.mkv
1846
+
1847
+ So this exists mostly out of convenience really.
1848
+
1849
+ In the long run it is planned to add many more conversion
1850
+ methods, such as **MultimediaParadise.to_avi()** and so
1851
+ forth. (The <b>multimedia_paradise gem</b> will attempt to
1852
+ use the most logical parameters here, if parameters are
1853
+ needed. Usually this just means **-vcodec copy** and
1854
+ **-acodec copy**, but this may not always be the case;
1855
+ sometimes re-encoding may occur, such as when dealing
1856
+ with very old video and audio codecs. But right now,
1857
+ it'll default to **copy**, for convenience and
1858
+ simplicity.)
1859
+
1860
+ ## Converting to a .flac file
1861
+
1862
+ You can use the following API to convert a file, such as foobar.mp3,
1863
+ into a .flac file:
1864
+
1865
+ MultimediaParadise.to_flac()
1866
+ MultimediaParadise.to_flac('foobar.mp3')
1867
+
1868
+ This functionality depends on ffmpeg. The method was added mostly
1869
+ for convenience-reasons, as the syntax for ffmpeg itself is
1870
+ fairly simple: <b>ffmpeg -i input.mp3 output.flac</b>
1871
+
1872
+ ## Converting to an .aac file
1873
+
1874
+ The following API can be used to convert an audio file into a
1875
+ .aac file, via ffmpeg and the <b>libvorbis</b> audio codec:
1876
+
1877
+ MultimediaParadise.mp3_to_aac()
1878
+ MultimediaParadise.to_aac() # This variant is shorter.
1879
+
1880
+ ## Conversions that are supported (table)
1881
+
1882
+ This table is mostly an overview of what is specifically supported
1883
+ by the multimedia_paradise gem as of May 2022.
1884
+
1885
+ Conversion | Comment
1886
+ --------------------|------------------------------------
1887
+ to_aac | convert into .aac format
1888
+ to_ogg | convert into .ogg format
1889
+ to_aiff | convert into .aiff format
1890
+ to_wav | convert into .wav format
1891
+ to_webm | convert into .webm format
1892
+ to_mkv | convert into .mkv format
1893
+ to_dv | convert into .dv format (Digital Video)
1894
+
1895
+ ## Converting a video file to the corresponding images
1896
+
1897
+ Via the toplevel method:
1898
+
1899
+ MultimediaParadise.video_to_images
1900
+
1901
+ you can <b>convert a video to its corresponding images</b>.
1902
+
1903
+ The first argument to this method should be the <b>filename</b>
1904
+ of the video-file. Specific example for this:
1905
+
1906
+ MultimediaParadise.video_to_images("foobar.mp4")
1907
+
1908
+ The second argument is the image format to use. You can just pass
1909
+ the Symbol :default here if you don't care about the format;
1910
+ this will then default to the <b>.jpg</b> format.
1911
+
1912
+ The <b>third argument</b> is the framerate, e. g. how many frames
1913
+ to convert into images per second. The default here currently is
1914
+ <b>25</b>. Some videos require more or fewer images per second,
1915
+ so you may want to change this is you feel you get too many or
1916
+ too few images.
1917
+
1918
+ Usage example if you want to do only one image per second:
1919
+
1920
+ MultimediaParadise.video_to_images("foobar.mp4", :default, 1)
1921
+
1922
+ See the file **multimedia_paradise/toplevel_methods/conversion.rb**
1923
+ for more information about that functionality - it is made possible
1924
+ thanks to ffmpeg.
1925
+
1926
+ ## Radio stations and a graphical user interface to it (GUI)
1927
+
1928
+ Since as of **October 2018**, the **MultimediaParadise** project comes
1929
+ with a small **yaml file** called **radio_stations.yml**.
1930
+
1931
+ x = YAML.load_file('radio_stations.yml')
1932
+
1933
+ The idea here is to have a few additional audio-streams (from **radio
1934
+ stations**) that could be loaded up into, for example, **rhythmbox**.
1935
+
1936
+ I also wanted to have a default "template" for testing some ruby code
1937
+ there, such as autogenerating a playlist from this file, or listening
1938
+ to radio stations via mplayer (or mpv) and similar activities.
1939
+
1940
+ The file **radio_stations.yml** is evidently catered to my own use
1941
+ case. If you wish to use your own .yml file then you can do so by
1942
+ setting the environment variable called **MULTIMEDIA_PARADISE_RADIO_STATIONS**
1943
+ to the path of a **local yaml file**. For the necessary format, see the
1944
+ file **radio_stations.yml** that comes distributed with this **.gem**.
1945
+ Or, you can simply modify the .yml file as-is and add/remove any
1946
+ entries; keep a backup just in case perhaps.
1947
+
1948
+ I may listen to local internet radio stations but also to external
1949
+ ones, such as **BBC**. The following example shows how I tap into
1950
+ this functionality via the commandline, first by showing **BBC 1**:
1951
+
1952
+ multimedia_paradise --bbc1
1953
+ multimedia_paradise --bbc2
1954
+ multimedia_paradise --bbc3
1955
+ multimedia_paradise --bbc4
1956
+ multimedia_paradise --fm4
1957
+
1958
+ The above list may be extended in the future, but for now (December
1959
+ 2018) it shall suffice.
1960
+
1961
+ Do note that this functionality depends on a multimedia player,
1962
+ such as **mpv** or **mplayer**. See elsewhere in this document
1963
+ how to set to use such a multimedia player, as far as the
1964
+ multimedia_paradise gem is concerned.
1965
+
1966
+ If you would rather prefer a GUI than have to use the commandline,
1967
+ you could use **gtk_radio**, available under the bin/ directory.
1968
+
1969
+ This **gtk-radio** gtk-widget even has a stop/play/resume button,
1970
+ and an **increase/decrease** in audio volume, **if ALSA is available**.
1971
+ This GUI will list some radio stations, based on a .yml file - you
1972
+ could use the same format and supply your own .yml file there
1973
+ should you wish to use other radio stations, but support for this
1974
+ has not yet been added (need to re-think that part; or you just
1975
+ modify the .yml file as it is, then start the gtk-radio - that
1976
+ should work fine as well if you feel like doing this. After all
1977
+ it is just data stored in yaml, nothing magic about it. I may
1978
+ also add more radio stations if someone sends me a sensible list
1979
+ of these to be included by default via an email, but please include
1980
+ all relevant details about that radio station, most importantly
1981
+ the remote URL in order to tap into the remote stream; right
1982
+ now **mpv** is used for this functionality, so if that information
1983
+ is not available then the stream can not possibly work).
1984
+
1985
+ Evidently LOTS of features are missing that might make sense
1986
+ for any **GUI** about radio-streams, and some bugs may exist as well,
1987
+ so don't use any of these widgets in "production" or for anything
1988
+ serious. I will, however had, try to make the GUI components,
1989
+ including the www-interfaces, more useful over the coming months
1990
+ and years, as time (and motivation) permits.
1991
+
1992
+ Note that for the first 10 buttons, you can **access** them via the
1993
+ **keyboard** too - by pressing ALT+number, such as **ALT+1** for
1994
+ the first button.
1995
+
1996
+ There is also a small bug right now in that mpv will continue
1997
+ to play sometimes, e. g. when the PID was not registered
1998
+ correctly. I have to pkill this from the commandline right now;
1999
+ one day in the future this bug will be squished, but for now
2000
+ it is better to document it as-is.
2001
+
2002
+ Next a few links that may be useful if you have to find out
2003
+ URLs to playlists:
2004
+
2005
+ https://marijanbloggt.at/2021/01/links-zu-streams-der-oesterreichischen-radiosender/120920
2006
+
2007
+ The ruby-gtk3 client currently looks like this (on IceWM):
2008
+
2009
+ <img src="https://i.imgur.com/O3K5XI9.png" style="margin: 1em">
2010
+
2011
+ This is far from perfect, but as a first step it should work
2012
+ somewhat ok-ish, as of <b>May 2022</b>. At a later time this
2013
+ may be improved visually, but for now it is how it is.
2014
+
2015
+ In <b>April 2023</b> this was changed a bit; a mute/unmute button was
2016
+ added too (requires ALSA on Linux).
2017
+
2018
+ It now looks like this:
2019
+
2020
+ <img src="https://i.imgur.com/ZCwo832.png" style="margin: 1em">
2021
+
2022
+ Not sure if this was an actual improvement, but for now it'll stay
2023
+ that way.
2024
+
2025
+ ## Converting a .mp4 or .avi file to an animated .gif
2026
+
2027
+ You can use the following API to convert a video to an
2028
+ animated .gif:
2029
+
2030
+ MultimediaParadise.to_gif('foobar.mp4')
2031
+
2032
+ I have not yet found a way to keep a high quality here,
2033
+ though, so the produced .gif is not really great. Perhaps
2034
+ someone finds out how to keep a higher quality here.
2035
+
2036
+ ## Querying the video codec in use
2037
+
2038
+ If you have ffmpeg installed then you can query the video
2039
+ codec in use via:
2040
+
2041
+ MultimediaParadise.return_video_codec_of_this_file
2042
+ MultimediaParadise.video_codec?
2043
+ MultimediaParadise.return_video_codec_of_this_file('foobar.mp4')
2044
+ MultimediaParadise.video_codec?('foobar.mp4')
2045
+
2046
+ This currently only works if a video has one stream. I do not
2047
+ know of a working syntax for querying all video streams in
2048
+ use, if a file has more than one stream, so keep this in mind.
2049
+ Most video files have only one stream though, so this method
2050
+ should work fine.
2051
+
2052
+ There is also an executable tying that functionality together,
2053
+ at <b>bin/video_codec</b>. It may then return a String on the
2054
+ commandline, such as "mpeg4".
2055
+
2056
+ ## GUI components of the multimedia_paradise project
2057
+
2058
+ ### Thoughts about GUIs in the multimedia_paradise gem
2059
+
2060
+ In December 2022 this subsection was re-arranged, to make
2061
+ it easer to focus on GUIs.
2062
+
2063
+ When we here refer to GUIs, note that web-applications,
2064
+ such as via sinatra, are included into this use case,
2065
+ as well as other languages, such as Java. Nonetheless,
2066
+ an important focus will also be on classical GUI elements,
2067
+ such as via ruby-gtk3 or ruby-libui.
2068
+
2069
+ The following subsections will detail more about the GUI
2070
+ components that are part of this project.
2071
+
2072
+ ### Graphical User Interface (GUI) and the MultimediaParadise project
2073
+
2074
+ A **Graphical User Interface** provides a human user with **a simplified
2075
+ way to interact with a computer**, via software.
2076
+
2077
+ Traditionally this was done primarily via a **desktop-computer**, the
2078
+ **mouse** (the pointer interface), the keyboard and a monitor. Nowadays
2079
+ the **www** is often used as a 'replacement' for these older graphical
2080
+ user interfaces, so some shift has definitely occurred, in particular
2081
+ in favour of 'smart' phones.
2082
+
2083
+ This evidently changed the way how users interact with these devices;
2084
+ typically no large keyboard is available on most of these devices, and
2085
+ an additional obvious constraint is the small screen estate.
2086
+
2087
+ My own primary focus, however had, is still centered around **oldschool
2088
+ classical desktop computers**, and **laptops** similar to such desktop
2089
+ computers, so I am **not** primarily concerned with smaller devices as
2090
+ such when it comes to **GUIs** in general. Perhaps at some later point
2091
+ in time this may change, but not for now. (In ruby-gtk3 this should
2092
+ be easily solvable via the **CSS support** anyway, so we could **use
2093
+ different style sheets**, depending on the interface at hand.)
2094
+
2095
+ How does this relate to the **multimedia_paradise project**?
2096
+
2097
+ The **multimedia_paradise project** tries to make use of GUIs as
2098
+ well.
2099
+
2100
+ Specifically you may be able to find **ruby-gtk** code that is
2101
+ distributed via the MultimediaParadise project that could be useful
2102
+ in this regard. In the past ruby-gtk2 was used for this project, but
2103
+ since as of the year **2021** ruby-gtk3 is the new default for all
2104
+ my projects when it comes to GUIs via gtk - including the MultimediaParadise
2105
+ project. I will not necessarily obsolete the old ruby-gtk2 deliberately
2106
+ so, mind you, but **new code** written will be in ruby-gtk3 most assuredly,
2107
+ and enabling ruby-gtk2 functionality is no longer a priority in this
2108
+ regard - at the least not for this project. Perhaps at one point in the
2109
+ future ruby-gtk2 will be viable again, but since GTK version 4.x
2110
+ is already released upstream, I think it is time to move on and away
2111
+ from GTK+-2.0, even though I still like this older GTK version. I am
2112
+ still using a GTK+-2.0 based editor, for instance.
2113
+
2114
+ The GTK-code made available as part of this project, in turn, depends
2115
+ on the project called **gtk_paradise**, as that project handles
2116
+ gtk-related parts, aside from the official upstream gtk3 gem of
2117
+ course. So make sure to install it as well, via
2118
+ **gem install gtk_paradise**.
2119
+
2120
+ Note that in general a lot of the GUI parts of MultimediaParadise
2121
+ are in an **extremely** **experimental** state, subject to change,
2122
+ and possibly filled with many unknown (and a few known) bugs -
2123
+ but you can have a look at some of the GUIs to see how they fare
2124
+ so far. An example would be the **gtk-radio** GUI component in
2125
+ particular, for ruby-gtk3. That one should work somewhat ok, although I
2126
+ have tested it mostly on non-systemd linux distributions only. On
2127
+ such a system it works quite ok-ish; the process-ID killing of mpv
2128
+ is super-hackish though. On windows with WSL enabled, it does not
2129
+ quite work yet, though; I have to find out how to be able to play
2130
+ sound on windows via WSL. Perhaps WSL2 simplifies this, I don't know
2131
+ yet.
2132
+
2133
+ Since as of **November 2020** a basic GUI has been added that allows
2134
+ the user to **tag .mp3 files with appropriate meta-data**. This is
2135
+ stored in the file called **tag_mp3_files.rb**. (The old name
2136
+ was **id_renamer**, but this was changed in **September 2021**
2137
+ when the application was rewritten.)
2138
+
2139
+ class **MultimediaParadise::GUI::Gtk::TagMp3Files** depends on
2140
+ the external library called **taglib** (**gem install taglib-ruby**),
2141
+ and the ruby bindings to that library, so make sure these are
2142
+ installed.
2143
+
2144
+ In the coming months this gtk-widget may be improved, but don't
2145
+ expect too many more upgrades to it for now - I am just glad to
2146
+ have finished it for now. It is more a 'fancy prototype' then a
2147
+ truly grandesque GUI. :)
2148
+
2149
+ You can also start this widget from the commandline, provided that
2150
+ you have the ruby-gtk bindings installed.
2151
+
2152
+ Example for that, on the commandline:
2153
+
2154
+ multimedia --gtk-tag
2155
+ multimedia --tagger
2156
+
2157
+ In **August 2021** a few things were added and it looks a bit
2158
+ better than it did a year ago. The current iteration looks
2159
+ like this on Linux (icewm) - may look different on GNOME or
2160
+ KDE depending on the theme in use:
2161
+
2162
+ <img src="https://i.imgur.com/9QIPEOn.png" style="margin-left: 2em">
2163
+
2164
+ In **September 2021** this was rewritten slightly and it looks
2165
+ a bit better now, in my opinion although it stayed mostly the
2166
+ same nonetheless. You can compare the two images here:
2167
+
2168
+ <img src="https://i.imgur.com/MnKgSUF.png" style="margin-left: 2em">
2169
+
2170
+ A new button was added as well - the one where you can randomly
2171
+ open a file. This allowed me to more rapidly go through the
2172
+ audio files and tag them appropriately so.
2173
+
2174
+ Since as of **February 2021**, there is also a video-editor prototype
2175
+ available. I will add more functionality to it over the coming months,
2176
+ but this is a slow project, since it is a hobby-based project. The
2177
+ goal here would be to eventually show a per-frame widget of the
2178
+ video, and allow the user to make modifications to it as-is.
2179
+
2180
+ Since as of **2021** I am also adding libui-specific widgets. This
2181
+ will not look as pretty as ruby-gtk3, but the benefit is that this
2182
+ will work on windows, out-of-the-box by default, whereas setting
2183
+ up GTK on windows is much harder.
2184
+
2185
+ I will keep a list of which widgets are implemented (even if it
2186
+ is only partially implemented).
2187
+
2188
+ youtube_downloader.rb # (1)
2189
+ lyrics.rb # (2)
2190
+ video_player.rb # (3)
2191
+ simple_play_widget.rb # (4) missing scrolled-window support in libui, though
2192
+ youtube_channels.rb # (5) quite ok; opening in the browser does not work very well on windows right now, in August 2021, though
2193
+ widget_increase_or_decrease_audio.rb # (6)
2194
+
2195
+ The following widgets still have to be ported:
2196
+
2197
+ cut_multimedia.rb
2198
+ id_renamer.rb
2199
+ multimedia_converter.rb
2200
+ multimedia_notebook.rb
2201
+ playlist.rb
2202
+ play_video_from_my_collection.rb
2203
+ radio.rb
2204
+ sound_effect_widget.rb
2205
+ video_collection.rb
2206
+ video_editor.rb
2207
+
2208
+ If you want to start the simple_play_widget.rb on windows,
2209
+ you can do this:
2210
+
2211
+ multimedia_paradise --simple-play-widget
2212
+
2213
+ ### Usability of the GUI components that are part of the multimedia_paradise gem
2214
+
2215
+ I am experimenting right now, and not all GUI components may
2216
+ be very useful. Nonetheless, if other users are interested
2217
+ in GUIs, let me know what you think about the various ruby-gtk3
2218
+ components that are part of the multimedia_paradise project.
2219
+
2220
+ Many of them are incomplete or buggy, but some parts tend to
2221
+ work somewhat ok-ish. I am curious which parts of the GUI
2222
+ tools should be improved next or extended, and how. For this,
2223
+ feedback would be helpful and appreciated.
2224
+
2225
+ ### Play videos from my collection via ruby-gtk3
2226
+
2227
+ The example file at:
2228
+
2229
+ gui/gtk3/play_video_from_my_collection/play_video_from_my_collection.rb
2230
+
2231
+ Can be used to play video files from a .yml collection. This
2232
+ even has a search widget which can be triggered by hitting:
2233
+
2234
+ Ctrl+F
2235
+
2236
+ As key combination.
2237
+
2238
+ The .yml file is adjusted to my own use case and collection
2239
+ so it may be utterly useless for other people - but it shows
2240
+ you how this works, hence why this is bundled into this project
2241
+ as well. If you want your own dataset, simply arrange them
2242
+ accordingly and change that .yml file.
2243
+
2244
+ The yaml file is normally at:
2245
+
2246
+ multimedia_paradise/yaml/video_collection/video_collection.yml
2247
+
2248
+ ### class MultimediaParadise::GUI::Gtk::ChangeMetadataWidget
2249
+
2250
+ You can use class **MultimediaParadise::GUI::Gtk::ChangeMetadataWidget**
2251
+ to change the meta-data of video files.
2252
+
2253
+ This currently (February of 2021) looks like this via ruby-gtk3:
2254
+
2255
+ <img src="https://i.imgur.com/ZzAUIoP.png" style="margin: 1em">
2256
+
2257
+ Not very pretty, but I only wanted to show the basic functionality
2258
+ around this. Perhaps in the future this may be improved, but
2259
+ since this is mostly just a hobby and "throw-away" script please
2260
+ do not expect this to become really polished. I only wanted to
2261
+ showcase the functionality, then move on.
2262
+
2263
+ ### class MultimediaParadise::GUI::LibUI::CutMultimedia
2264
+
2265
+ This class can be used on windows, if you have ffmpeg installed,
2266
+ to cut audio files. You can download some windows binaries
2267
+ from the internet for this; I put ffmpeg.exe in /usr/bin/ -
2268
+ easier to remember for me, even on windows.
2269
+
2270
+ In <b>December 2022</b> I tested this functionality - and it
2271
+ works, on windows as well. \o/
2272
+
2273
+ This functionality that this GUI offers is not very advanced as
2274
+ of yet. At a later time this may be extended. For now (December
2275
+ 2022) it was more important to simply add this functionality.
2276
+
2277
+ ## Creating looping video files
2278
+
2279
+ ffmpeg allows us to create a <b>video playback loop</b> of a
2280
+ given video. Let's assume we have the file called <b>foobar.webm</b>.
2281
+ How to loop this video file, via ffmpeg?
2282
+
2283
+ ffmpeg -stream_loop 10 -i input_file_goes_here.webm -c copy foobar.webm
2284
+
2285
+ The above commandline example would loop the given video file
2286
+ 10 times. That is as if you were to play it 10 times in a
2287
+ row without delay.
2288
+
2289
+ As the above functionality seemed useful, it was added to the
2290
+ multimedia_paradise gem in January 2023.
2291
+
2292
+ Usage example:
2293
+
2294
+ MultimediaParadise.loop_this_video('input_file.webm', 10)
2295
+ MultimediaParadise.loop_this_video('input_file.webm', '10 times')
2296
+ MultimediaParadise.loop_this_video('input_file.webm', '10x')
2297
+
2298
+ The above is all synonymous, but the first variant is probably the
2299
+ easiest to use.
2300
+
2301
+ ## class MultimediaParadise::Video::SplitThisVideo
2302
+
2303
+ class MultimediaParadise::Video::SplitThisVideo was added in February
2304
+ 2023 to allow us to easily split a video file.
2305
+
2306
+ Usage example:
2307
+
2308
+ require 'multimedia_paradise/video/split_this_video.rb'
2309
+ MultimediaParadise::Video::SplitThisVideo.new(ARGV)
2310
+ MultimediaParadise::Video::SplitThisVideo.new('foobar.avi','00:23')
2311
+
2312
+ You need to pass the time in 24-hour notation for now. At a later time
2313
+ this restriction will be relaxed.
2314
+
2315
+ I aliased this to split_this_video on the commandline. Then I can do
2316
+ this from the commandline:
2317
+
2318
+ splitthisvideo foobar.mpg 00:00-21:39.40
2319
+
2320
+ ## Documentation in the multimedia_paradise/www directory
2321
+
2322
+ In the past the multimedia_paradise gem carried documentation, in the
2323
+ form of .cgi pages and .sinatra files, under the directory
2324
+ <b>multimedia_paradise/www</b>.
2325
+
2326
+ This was mostly as a focus on audio and video related data, to
2327
+ help us when we want to manipulate such datasets.
2328
+
2329
+ In <b>March 2023</b>, however had, I reconsidered the old approach, and
2330
+ decided to put all this documentation in the <b>roebe</b> gem
2331
+ instead. That gem is where I unify most of my other projects,
2332
+ including documentation. I use that gem a bit like a local wiki.
2333
+
2334
+ ## class MultimediaParadise::Video::FindVideo
2335
+
2336
+ class <b>MultimediaParadise::Video::FindVideo</b> can be used to
2337
+ find a video registered in the local yaml file - or a yaml file
2338
+ supplied.
2339
+
2340
+ The multimedia_paradise gem comes with a yaml file that carries
2341
+ the dataset I use for my local video collection.
2342
+
2343
+ This file can be found here:
2344
+
2345
+ multimedia_paradise/yaml/video_collection/video_collection.yml
2346
+
2347
+ Obviously this is catered to my own use case and preferences so
2348
+ it will be totally useless to other folks. But it documents
2349
+ the format I use, and you can just re-use it to adjust it to
2350
+ your own use case.
2351
+
2352
+ In <b>April 2023</b> class <b>MultimediaParadise::Video::FindVideo</b>
2353
+ was rewritten. It now allows users to supply their own .yml file
2354
+ too. That way users of this gem can work on their own dataset,
2355
+ as-is.
2356
+
2357
+ What is the use case for class <b>MultimediaParadise::Video::FindVideo</b>?
2358
+
2359
+ This class will simply find where exactly a video file is kept
2360
+ at. This includes support for numeric values.
2361
+
2362
+ For instance, I wanted to be able to do this:
2363
+
2364
+ play_video 235
2365
+
2366
+ And it should play the video that is at position 235 in that
2367
+ yaml file (or in the current working directory, if there is
2368
+ any video file that has the string "235" as part of its
2369
+ filename).
2370
+
2371
+ That way I can quickly play my local video files, without
2372
+ having to determine whether the file may actually be, or
2373
+ what the full name is. I can also supply a partial name,
2374
+ such as "shrek", which would expand towards the real file
2375
+ name of shrek 1 (the movie). This flexibility allows me to
2376
+ play video files from the commandline via mplayer or mpv.
2377
+
2378
+ So this is mostly a convenience class really.
2379
+
2380
+ You can supply your own yaml file via:
2381
+
2382
+ find_video --use-this-yaml-file=foobar.yml
2383
+
2384
+ ## Dealing with broken .mpg video files, including repairing them
2385
+
2386
+ I have some old video files, created by other people, most of them
2387
+ in .mpg format; some in container formats such as .avi.
2388
+
2389
+ Some of these have issues, such as:
2390
+
2391
+ [ffmpeg/audio] mp2: Header missing
2392
+ Error decoding audio.
2393
+
2394
+ So, evidently, the audio has a problem here.
2395
+
2396
+ We should fix this - and ffmpeg may come to the rescue. \o/
2397
+
2398
+ Interestingly, to fix the above error, a simple -c copy
2399
+ can work.
2400
+
2401
+ Example:
2402
+
2403
+ ffmpeg -i input.mpg -c copy output.mpg
2404
+ ffmpeg -i input.mpg -c copy output.mp4
2405
+
2406
+ Here both options should do fairly well; I got rid of the
2407
+ above error when I tried this in October 2023.
2408
+
2409
+ However had, the file output.mpg still raised errors
2410
+ such as:
2411
+
2412
+ [ffmpeg/demuxer] mpeg: DTS discontinuity in stream 1: packet 3 with DTS 104041, packet 4 with DTS 111240
2413
+ [ffmpeg/demuxer] mpeg: DTS discontinuity in stream 1: packet 5 with DTS 111241, packet 6 with DTS 118440
2414
+ [ffmpeg/demuxer] mpeg: DTS discontinuity in stream 1: packet 7 with DTS 118441, packet 8 with DTS 125640
2415
+
2416
+ Whereas the .mp4 file created does not yield to errors. So I
2417
+ think converting a .mpg file into a .mp4 is in general better.
2418
+
2419
+ At any rate, that got rid of the error above. But .mpg files
2420
+ are fairly large and I wanted to also decrease the file size.
2421
+ However had that is handled via another subsection in this
2422
+ file - please jump towards
2423
+ <b>Converting a .mpg file into a .mp4 file</b>.
2424
+
2425
+ ## Converting a .mpg file into a .mp4 file
2426
+
2427
+ The simplest way possible is probably this:
2428
+
2429
+ ffmpeg -i input.mp4 -vcodec libx265 -crf 18 -tag:v hvc1 -preset veryslow output.mp4
2430
+ ffmpeg -i input.mpg -vcodec libx265 -crf 18 -tag:v hvc1 -preset veryslow output.mp4
2431
+
2432
+ Note that a value to crf of 0, aka <b>-crf 0</b>, would
2433
+ mean that there is lossless conversion. But the file
2434
+ size may be quite large, so we use a value of 18 in the
2435
+ above example instead.
2436
+
2437
+ When I tried the -crf option, though, ffmpeg reported
2438
+ this error:
2439
+
2440
+ Unrecognized option 'crf'.
2441
+ Error splitting the argument list: Option not found
2442
+
2443
+ So right now I am a bit stuck. This may mean that the libx265
2444
+ encoder was not found.
2445
+
2446
+ The following has worked, but it only copies the audio-codec and
2447
+ the video codec:
2448
+
2449
+ fmpeg -i "foobar.mpg" -acodec copy -vcodec copy -f mp4 barfoo.mp4
2450
+
2451
+ I eventually recompiled ffmpeg, and then the commandline variant
2452
+ was suddenly working - so, indeed, make sure your ffmpeg installation
2453
+ has the required codecs compiled in.
2454
+
2455
+ Here was the commandline variant I used:
2456
+
2457
+ ffmpeg -i foobar.mpg -c:v libx264 -c:a libfaac -crf 20 -preset:v veryslow output.mp4
2458
+
2459
+ That led to fairly large video files though.
2460
+
2461
+ I then tested this variant:
2462
+
2463
+ ffmpeg -i foobar.mpg -c:v libx265 -c:a libmp3lame -crf 28 -preset:v veryslow ANOTHER_EXAMPLE.mp4
2464
+
2465
+ This one seems to have better results. x265 also in general appears
2466
+ to be a significantly better codec than x264, so it should be used.
2467
+
2468
+ You may have to adjust the -crf value, but I ended up with a file
2469
+ size reduction of 75% of one .mpg file. Again, I am not sure how
2470
+ much the quality differs, but I think I may stick with the above
2471
+ values for the time being.
2472
+
2473
+ The above flags were also put into a bin/ executable, called
2474
+ <b>bin/mpg_to_mp4</b>. So the commandline invocation would
2475
+ be:
2476
+
2477
+ mpg_to_mp4 foobar.mpg
2478
+
2479
+ ## Extracting audio from any given video file
2480
+
2481
+ You can extract audio from any given video file, by making
2482
+ use of <b>class MultimediaParadise::ExtractAudio</b>. This
2483
+ presently depends on <b>ffmpeg</b>, so you must have
2484
+ ffmpeg available.
2485
+
2486
+ A specific usage example follows, including the require line
2487
+ that could be used:
2488
+
2489
+ require 'multimedia_paradise/audio/extract_audio/extract_audio.rb'
2490
+ MultimediaParadise::ExtractAudio.new('foobar.avi')
2491
+
2492
+ This assumes that a video file called **foobar.avi** exists.
2493
+
2494
+ A **toplevel method** exists for this functionality as well:
2495
+
2496
+ MultimediaParadise.extract_audio(target_file_here)
2497
+ MultimediaParadise.extract_audio('/tmp/foobar.avi')
2498
+ MultimediaParadise.extract_audio('/home/lala.mp4')
2499
+
2500
+ Perhaps you may find the latter variant to be easier to read and
2501
+ use than the variant that uses explicit **::** scoping for the
2502
+ instantiation of **class ExtractAudio**. Under the hood, both
2503
+ variants do the same of course.
2504
+
2505
+ ## Extracting images from a video file
2506
+
2507
+ The following toplevel method can be used to extract images from
2508
+ a video file:
2509
+
2510
+ MultimediaParadise.extract_images_from_this_video_file('100_0002.mov')
2511
+
2512
+ Simply pass in the file. This defaults to one-image-per-second, which
2513
+ is controlled via the second argument to this method, defaulting
2514
+ to <b>1</b>.
2515
+
2516
+ I recommend to use a standalone directory for this, as quite many
2517
+ .png files may be created as a result.
2518
+
2519
+ ## Creating a thumbnail from a video via ffmpeg
2520
+
2521
+ In <b>May 2023</b> I read that it is possible to create a thumbnail
2522
+ for a video, using ffmpeg.
2523
+
2524
+ The guide I was looking at was originally available here:
2525
+
2526
+ https://www.bannerbear.com/blog/how-to-set-a-custom-thumbnail-for-a-video-file-using-ffmpeg/
2527
+
2528
+ Since this was quite useful, I decided to add support for this to
2529
+ the multimedia_paradise gem.
2530
+
2531
+ The functionality and API will be demonstrated on a locally existing
2532
+ file. For the purpose of this document, I will use this file:
2533
+
2534
+ this_file = '/Depot/j/foobar.mp4'
2535
+
2536
+ Adjust to your use case accordingly.
2537
+
2538
+ Now that we have such a file, we need to know the ffmpeg-syntax to
2539
+ obtain a specific frame from a video file.
2540
+
2541
+ The following command will obtain the first frame of the video
2542
+ specified at the path above, in pure ffmpeg syntax (on the
2543
+ commandline):
2544
+
2545
+ ffmpeg -i /Depot/j/foobar.mp4 -frames:v 1 /Depot/j/a_new_screenshot.png
2546
+
2547
+ This should have created the file <b>/Depot/j/a_new_screenshot.png</b>.
2548
+
2549
+ However had, in many cases this will be a black screen image, which is
2550
+ not too terribly useful.
2551
+
2552
+ So another way may be useful here. We can tell ffmpeg to use a specific
2553
+ timestamp.
2554
+
2555
+ For instance, to capture the specific frame at <b>15.0 seconds</b>, use
2556
+ the following command:
2557
+
2558
+ ffmpeg -ss 00:00:15 -i /Depot/j/foobar.mp4 -frames:v 1 ss-0015.png
2559
+
2560
+ (It is recommended to use the --ss option as early as possible,
2561
+ even before the actual filename.)
2562
+
2563
+ Now things get more interesting.
2564
+
2565
+ FFmpeg has many built-in filters. One of these filters is the <b>Thumbnail
2566
+ filter</b>. That filter will <b>automatically</b> select the most representative
2567
+ frame in a given sequence of consecutive frames from the video. This is
2568
+ <b>great</b>! \o/
2569
+
2570
+ How is that feature used in raw ffmpeg? Well, add the -vf "thumbnail"
2571
+ instructions onto the commandline.
2572
+
2573
+ Example:
2574
+
2575
+ ffmpeg -i /Depot/j/foobar.mp4 -vf "thumbnail" -frames:v 1 thumbnail.png
2576
+
2577
+ "<b>thumbnail</b>" is the name of the filter, whereas -vf is
2578
+ simply an alias for <b>-filter:v</b>.
2579
+
2580
+ By default, FFmpeg analyzes the frames in a batch of 100 before it then
2581
+ picks the most representative frame out of that batch. The process will
2582
+ continue until the end of the video, making sure that the best frame among
2583
+ all batches has been chosen for that video.
2584
+
2585
+ The batch size can be set on the commandline, via:
2586
+
2587
+ thumbnail = n # n is the number of frames.
2588
+
2589
+ So, for instance, if you want to pick a batch size of 300, you would
2590
+ use this:
2591
+
2592
+ ffmpeg -i /Depot/j/foobar.mp4 -vf "thumbnail=300" -frames:v 1 thumbnail-300.png
2593
+
2594
+ Keep in mind that <b>a high value for n</b> means that more memory will
2595
+ be used, so this may be slow on older computers. 100 seems a decent
2596
+ default option to use here. (Note that I modify this value every
2597
+ now and then to see whether I get better results; in November 2023
2598
+ I am experimenting with the value 150. You may have to adjust the
2599
+ value for your own use cases.)
2600
+
2601
+ Within the multimedia_paradise gem, the following API allows you to
2602
+ automatically create a thumbnail from a video file.
2603
+
2604
+ Usage example:
2605
+
2606
+ require 'multimedia_paradise/toplevel_methods/misc.rb' # ← This file includes the code shown below.
2607
+ this_file = '/Depot/j/foobar.mp4'
2608
+
2609
+ MultimediaParadise.automatically_create_a_thumbnail_for_this_video()
2610
+ MultimediaParadise.automatically_create_a_thumbnail_for_this_video(this_file)
2611
+ MultimediaParadise.thumbnail(this_file) # ← This is an aliased API to the ^^^ above.
2612
+
2613
+ This method will return the newly generated image file. The name will be
2614
+ semi-generic, e. g. "thumbnail_for_", and then the raw filename of the
2615
+ file at hand, as a .png file. These raw filenames will be stored into
2616
+ an Array and this Array will then be returned, so you can write downstream
2617
+ code that depends on this.
2618
+
2619
+ The default option this method will use interally will be <b>thumbnail=100</b>.
2620
+ When I tested this in <b>May 2023</b>, this seemed to yield the best results.
2621
+
2622
+ Anyway - there are some other methods to choose "the best thumbnail", but
2623
+ for now the multimedia_paradise gem supports only the variant shown above.
2624
+ Perhaps at a later time this may be extended, but for now this is how it
2625
+ is.
2626
+
2627
+ We are not yet done, though. Now that we have the image, we must set the
2628
+ thumbnail for the video. This can be done by using the <b>map</b> option
2629
+ of ffmpeg. This option will choose which streams from the given input
2630
+ should be included in the (new) output.
2631
+
2632
+ The way how ffmpeg calls these options is slightly confusing. For instance,
2633
+ -map 1 refers to the input index #1, which is the second input.
2634
+ -map 0 refers to the input index #0, which is the first input - in
2635
+ our case the original video.
2636
+
2637
+ At any rate, to simplify this, prepare the .mp4 file and the image
2638
+ file, then do this:
2639
+
2640
+ ffmpeg -i /Depot/j/foobar.mp4 -i thumbnail.png -map 1 -map 0 -c copy -disposition:0 attached_pic output.mp4
2641
+
2642
+ This latter functionality was not yet added to the multimedia_paradise
2643
+ gem though - it may be added at a later time. I did, however had,
2644
+ test it via <b>dolphin</b> (from KDE) and it appears different when
2645
+ compared to the original .mp4 file, so the functionality provided
2646
+ by ffmpeg <b>does</b> work.
2647
+
2648
+ ## Learning to play the piano
2649
+
2650
+ Since a few months I am (again) learning to play the piano, although
2651
+ I use a Yamaha keyboard rather than a piano.
2652
+
2653
+ This subsection here will collect various snippets that may relate
2654
+ to playing songs. This is very random though.
2655
+
2656
+ Phantom of the Opera:
2657
+
2658
+ <img src="https://s3.amazonaws.com/halleonard-pagepreviews/HL_DDS_1287087dIYk05Nba7.png">
2659
+
2660
+ https://www.youtube.com/watch?v=jSWZzClCTVA
2661
+
2662
+
2663
+ ## Contact information and mandatory 2FA (no longer) coming up in 2022 / 2023
2664
+
2665
+ If your creative mind has ideas and specific suggestions to make this gem
2666
+ more useful in general, feel free to drop me an email at any time, via:
2667
+
2668
+ shevy@inbox.lt
2669
+
2670
+ Before that email I used an email account at Google gmail, but in **2021** I
2671
+ decided to slowly abandon gmail, for various reasons. In order to limit the
2672
+ explanation here, allow me to just briefly state that I do not feel as if I
2673
+ want to promote any Google service anymore when the user becomes the end
2674
+ product (such as via data collection by upstream services, including other
2675
+ proxy-services). My feeling is that this is a hugely flawed business model
2676
+ to begin with, and I no longer wish to support this in any way, even if
2677
+ only indirectly so, such as by using services of companies that try to
2678
+ promote this flawed model.
2679
+
2680
+ In regards to responding to emails: please keep in mind that responding
2681
+ may take some time, depending on the amount of work I may have at that
2682
+ moment. So it is not that emails are ignored; it is more that I have not
2683
+ (yet) found the time to read and reply. This means there may be a delay
2684
+ of days, weeks and in some instances also months. There is, unfortunately,
2685
+ not much I can do when I need to prioritise my time investment, but I try
2686
+ to consider <b>all</b> feedback as an opportunity to improve my projects
2687
+ nonetheless.
2688
+
2689
+ In <b>2022</b> rubygems.org decided to make 2FA mandatory for every
2690
+ gem owner eventually:
2691
+
2692
+ see
2693
+ https://blog.rubygems.org/2022/06/13/making-packages-more-secure.html
2694
+
2695
+ Mandatory 2FA will eventually be extended to all rubygems.org developers and
2696
+ maintainers. As I can not use 2FA, for reasons I will skip explaining here,
2697
+ this means that my projects will eventually be removed, as I no longer
2698
+ have any control over my projects hosted on rubygems.org (because I
2699
+ can not use 2FA).
2700
+
2701
+ At that point, I no longer have any control what is done to my projects
2702
+ since whoever is controlling the gems ecosystem took away our control
2703
+ here. I am not sure at which point ruby became corporate-controlled -
2704
+ that was not the case several years ago, so something has
2705
+ changed.
2706
+
2707
+ Ruby also only allows 2FA users to participate on the issue tracker these
2708
+ days:
2709
+
2710
+ https://bugs.ruby-lang.org/issues/18800
2711
+
2712
+ But this has been reverted some months ago, so it is no longer applicable.
2713
+ Suffice to say that I do not think that we should only be allowed to
2714
+ interact on the world wide web when some 'authority' authenticated us,
2715
+ such as via mandatory 2FA, so I hope this won't come back again.
2716
+
2717
+ Fighting spam is a noble goal, but when it also means you lock out
2718
+ real human people then this is definitely NOT a good situation
2719
+ to be had.
2720
+