ghost_youtube 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7aea7c97a21eb1feee65de32dfba250dde128f273e04dbe70e42d445bff1d1f9
4
+ data.tar.gz: 5e72801bda63c3e61cbca48f15c757190315bbd82ae819018f24dfd93b0d7642
5
+ SHA512:
6
+ metadata.gz: 4115cc8d836de229ba5c0e58fdaae6cf5660170f3e0656ddb4f85f3c634a72a5ef95953a9c5d99e9de4316e8353a1a14a78be7e758b240d5b8202e6c2abf195d
7
+ data.tar.gz: fa7ab99e242877ea5e5c7f37862a428ef5e452ecec703883778922558b70e5745a9a2a9625c9d3dbcf498580687d5f41aaf98f439cbbd328193a7397cbf405f7
data/Gemfile ADDED
@@ -0,0 +1,8 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem "rake"
7
+ gem "rspec"
8
+ end
data/LICENSE ADDED
File without changes
data/README.md ADDED
@@ -0,0 +1,236 @@
1
+ # Ghost YouTube Library
2
+
3
+ A lightweight Ruby gem for downloading videos, captions, and handling cookies with YouTube and Vimeo.
4
+
5
+ ## Requirements
6
+
7
+ * Ruby 2.5+
8
+ * [yt-dlp](https://github.com/yt-dlp/yt-dlp) must be installed on your system
9
+
10
+ ## Installation
11
+
12
+ ```bash
13
+ # Install yt-dlp first
14
+ pip install -U yt-dlp
15
+
16
+ # Install the gem
17
+ gem install ghost_youtube
18
+ ```
19
+
20
+ Or add it to your Gemfile:
21
+
22
+ ```ruby
23
+ gem 'ghost_youtube'
24
+ ```
25
+
26
+ ## Features
27
+
28
+ - Download YouTube videos with progress bar
29
+ - Download YouTube videos with specific quality
30
+ - Download YouTube captions
31
+ - Support for YouTube Shorts
32
+ - Support for Vimeo videos
33
+ - Support for using cookies to download videos
34
+
35
+ ## Usage Examples
36
+
37
+ ### 1. Basic Video Download
38
+
39
+ ```ruby
40
+ require 'ghost_youtube'
41
+
42
+ # Download a YouTube video with default options
43
+ video = Ghost::Download.youtube("https://www.youtube.com/watch?v=ocV8fBuzeh8")
44
+
45
+ # Download with full path
46
+ puts "Video saved to: #{video}"
47
+ ```
48
+
49
+ ### 2. Download with Progress Bar
50
+
51
+ ```ruby
52
+ require 'ghost_youtube'
53
+
54
+ # Download a YouTube video with a progress bar using "#" character
55
+ url = "https://www.youtube.com/watch?v=ocV8fBuzeh8"
56
+ Ghost::Download.youtube(url, pro: "#")
57
+
58
+ # You can use any character for the progress bar
59
+ Ghost::Download.youtube(url, pro: "█")
60
+ ```
61
+
62
+ ### 3. Download with Quality Settings
63
+
64
+ ```ruby
65
+ require 'ghost_youtube'
66
+
67
+ url = "https://www.youtube.com/watch?v=ocV8fBuzeh8"
68
+
69
+ # Download best quality
70
+ Ghost::Download.youtube(url, quality: "best")
71
+
72
+ # Download specific resolution
73
+ Ghost::Download.youtube(url, quality: "bestvideo[height<=720]+bestaudio")
74
+
75
+ # Video-only download (no audio)
76
+ Ghost::Download.youtube(url, sounde: false)
77
+ ```
78
+
79
+ ### 4. Download YouTube Shorts
80
+
81
+ ```ruby
82
+ require 'ghost_youtube'
83
+
84
+ # YouTube Shorts work the same way as regular videos
85
+ shorts_url = "https://www.youtube.com/watch?v=ocV8fBuzeh8"
86
+ Ghost::Download.youtube(shorts_url, quality: "best", pro: "#")
87
+ ```
88
+
89
+ ### 5. Download YouTube Captions
90
+
91
+ ```ruby
92
+ require 'ghost_youtube'
93
+
94
+ # Download captions in English
95
+ url = "https://www.youtube.com/watch?v=ocV8fBuzeh8"
96
+ captions = Ghost::Caption.youtube(url, language: "en")
97
+ puts "Caption file saved to: #{captions}"
98
+
99
+ # Download captions in a different language
100
+ captions_es = Ghost::Caption.youtube(url, language: "es")
101
+ ```
102
+
103
+ ### 6. Download Using Cookies
104
+
105
+ ```ruby
106
+ require 'ghost_youtube'
107
+
108
+ # Download a video using cookies (for age-restricted or private videos)
109
+ url = "https://www.youtube.com/watch?v=ocV8fBuzeh8"
110
+ cookies_path = "/path/to/your/cookies.txt"
111
+ video = Ghost::Cookies.youtube(url, cookies_file: cookies_path)
112
+ ```
113
+
114
+ ### 7. Download Vimeo Videos
115
+
116
+ ```ruby
117
+ require 'ghost_youtube'
118
+
119
+ # Download a Vimeo video
120
+ vimeo_url = "https://vimeo.com/12345678"
121
+ Ghost::Download.vimeo(vimeo_url)
122
+ ```
123
+
124
+ ### 8. Complete Example Script
125
+
126
+ ```ruby
127
+ require 'ghost_youtube'
128
+
129
+ puts "==== Ghost YouTube Downloader Demo ===="
130
+
131
+ # Define a video to download
132
+ video_url = "https://www.youtube.com/watch?v=ocV8fBuzeh8"
133
+
134
+ # Download a YouTube video with progress bar
135
+ puts "\n[1] Downloading video with progress bar..."
136
+ Ghost::Download.youtube(video_url, sounde: true, quality: "best", pro: "#")
137
+
138
+ # Download captions if available
139
+ puts "\n[2] Downloading captions..."
140
+ begin
141
+ Ghost::Caption.youtube(video_url, language: "en")
142
+ rescue => e
143
+ puts "Captions not available or error: #{e.message}"
144
+ end
145
+
146
+ # Download a YouTube Shorts
147
+ puts "\n[3] Downloading a YouTube Shorts..."
148
+ shorts_url = "https://www.youtube.com/watch?v=ocV8fBuzeh8"
149
+ Ghost::Download.youtube(shorts_url, quality: "best", pro: "=")
150
+
151
+ puts "\nDownloads completed!"
152
+ ```
153
+
154
+ ## Cookies Format
155
+
156
+ For age-restricted videos or videos that require login, you need to provide a cookies file.
157
+ You can export cookies from your browser using extensions like "Get cookies.txt" or "EditThisCookie".
158
+
159
+ The cookies file should be in Netscape format:
160
+
161
+ ```
162
+ # Netscape HTTP Cookie File
163
+ .youtube.com TRUE / FALSE 1739582099 GPS 1
164
+ .youtube.com TRUE / FALSE 1739582099 VISITOR_INFO1_LIVE aBcDeFgHiJk
165
+ .youtube.com TRUE / FALSE 1739582099 YSC AbCdEfGhIjK
166
+ ```
167
+
168
+ ## API Reference
169
+
170
+ ### Download Module
171
+
172
+ - `Ghost::Download.youtube(url, options = {})`
173
+ - `url`: YouTube video URL
174
+ - `options`:
175
+ - `sounde`: Boolean (default: true) - Download with audio
176
+ - `quality`: String (default: "best") - Quality selection
177
+ - `pro`: String or nil (default: nil) - Progress bar character
178
+
179
+ - `Ghost::Download.vimeo(url, options = {})`
180
+ - `url`: Vimeo video URL
181
+ - `options`: Currently not used
182
+
183
+ ### Caption Module
184
+
185
+ - `Ghost::Caption.youtube(url, language: 'en')`
186
+ - `url`: YouTube video URL
187
+ - `language`: String (default: 'en') - Caption language code
188
+
189
+ ### Cookies Module
190
+
191
+ - `Ghost::Cookies.youtube(url, cookies_file:)`
192
+ - `url`: YouTube video URL
193
+ - `cookies_file`: Path to cookies file in Netscape format
194
+
195
+ ## How It Works
196
+
197
+ Ghost YouTube uses the powerful [yt-dlp](https://github.com/yt-dlp/yt-dlp) program under the hood,
198
+ which is a feature-rich YouTube-DL fork with additional features and fixes.
199
+
200
+ The library provides a simple Ruby interface to access the most common functionality:
201
+
202
+ ```ruby
203
+ # This Ruby code:
204
+ Ghost::Download.youtube(url, sounde: true, quality: "best", pro: "#")
205
+
206
+ # Executes this command:
207
+ yt-dlp -f "bestvideo+bestaudio/best" --merge-output-format mp4 <url>
208
+ ```
209
+
210
+ ## Error Handling
211
+
212
+ The library provides specific error classes for different failure scenarios:
213
+
214
+ ```ruby
215
+ begin
216
+ Ghost::Download.youtube("https://invalid-url")
217
+ rescue Ghost::Errors::DownloadError => e
218
+ puts "Download failed: #{e.message}"
219
+ end
220
+
221
+ begin
222
+ Ghost::Caption.youtube("https://www.youtube.com/watch?v=ocV8fBuzeh8", language: "xx")
223
+ rescue Ghost::Errors::CaptionError => e
224
+ puts "Caption download failed: #{e.message}"
225
+ end
226
+
227
+ begin
228
+ Ghost::Cookies.youtube("https://www.youtube.com/watch?v=ocV8fBuzeh8", cookies_file: "/nonexistent/path")
229
+ rescue Ghost::Errors::CookiesError => e
230
+ puts "Cookies download failed: #{e.message}"
231
+ end
232
+ ```
233
+
234
+ ## License
235
+
236
+ This project is licensed under the terms of the MIT license.# ghost_youtube
@@ -0,0 +1,24 @@
1
+ # ghost_youtube.gemspec
2
+ Gem::Specification.new do |spec|
3
+ spec.name = "ghost_youtube"
4
+ spec.version = "0.1.0"
5
+ spec.authors = ["Maven"]
6
+
7
+ spec.summary = %q{A Ruby library to download YouTube videos with audio and captions of Videos}
8
+ spec.description = %q{
9
+ GhostYoutube is a pure Ruby gem that wraps the command-line tool, making it
10
+ easy to download YouTube videos, captions, and videos using cookies. It is designed
11
+ to be used in any Ruby environment (Ruby, Rails, JRuby, CRuby, etc.).
12
+ }
13
+ spec.homepage = "https://github.com/Abo5/ghost_youtube"
14
+ spec.license = "MIT"
15
+
16
+ spec.required_ruby_version = ">= 2.5.0"
17
+
18
+ spec.files = Dir["lib/**/*", "ghost_youtube.rb", "README.md", "LICENSE", "Gemfile", "ghost_youtube.gemspec"]
19
+ spec.executables = []
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
23
+ end
24
+
data/ghost_youtube.rb ADDED
@@ -0,0 +1,66 @@
1
+ # ghost_youtube.rb
2
+
3
+ # Ensure that yt-dlp is installed on the system.
4
+ def ensure_yt_dlp_installed
5
+ unless system("command -v yt-dlp > /dev/null 2>&1")
6
+ raise LoadError, "yt-dlp is not installed. Please install it from https://github.com/yt-dlp/yt-dlp"
7
+ end
8
+ end
9
+
10
+ ensure_yt_dlp_installed
11
+
12
+ require_relative 'lib/errors'
13
+ require_relative 'lib/download/youtube'
14
+ require_relative 'lib/download/vimeo'
15
+ require_relative 'lib/caption/youtube_caption'
16
+ require_relative 'lib/cookies/cookies_handler'
17
+
18
+ module Ghost
19
+ module Download
20
+ # DSL method for downloading a YouTube video.
21
+ # Example usage:
22
+ # Ghost::Download.youtube("url", sounde: true, quality: "best", pro: "#")
23
+ def self.youtube(url, options = {})
24
+ sound = options.fetch(:sounde, true)
25
+ # Fix spelling error in parameter name from qualtiy to quality
26
+ quality = options.fetch(:quality, "best")
27
+ # For backward compatibility with existing code
28
+ quality = options.fetch(:qualtiy, quality) if options.key?(:qualtiy)
29
+ progress_style = options.fetch(:pro, nil)
30
+
31
+ # Print debug information
32
+ puts "Downloading video from: #{url}"
33
+ puts "Video quality: #{quality}"
34
+ puts "Audio enabled: #{sound}"
35
+
36
+ downloader = Download::Youtube.new(url, quality: quality, sounde: sound, progress: progress_style)
37
+ downloader.download
38
+ end
39
+
40
+ # DSL method for downloading a Vimeo video.
41
+ def self.vimeo(url, options = {})
42
+ downloader = Download::Vimeo.new(url, options)
43
+ downloader.download
44
+ end
45
+ end
46
+
47
+ module Caption
48
+ # DSL method for downloading YouTube captions.
49
+ # Example usage:
50
+ # Ghost::Caption.youtube("url", language: "en")
51
+ def self.youtube(url, language: 'en')
52
+ caption_downloader = Caption::YoutubeCaption.new(url, language)
53
+ caption_downloader.download
54
+ end
55
+ end
56
+
57
+ module Cookies
58
+ # DSL method for downloading a YouTube video using cookies.
59
+ # Example usage:
60
+ # Ghost::Cookies.youtube("url", cookies_file: "path/to/cookies.txt")
61
+ def self.youtube(url, cookies_file:)
62
+ cookies_handler = Cookies::CookiesHandler.new(url, cookies_file)
63
+ cookies_handler.download
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,24 @@
1
+ # lib/caption/youtube_caption.rb
2
+ require 'open3'
3
+ require_relative '../errors'
4
+
5
+ module Ghost
6
+ module Caption
7
+ class YoutubeCaption
8
+ def initialize(url, language = 'en')
9
+ @url = url
10
+ @language = language
11
+ end
12
+
13
+ def download
14
+ command = "yt-dlp --write-auto-sub --sub-lang #{@language} --skip-download #{@url}"
15
+ stdout_str, stderr_str, status = Open3.capture3(command)
16
+ if status.success?
17
+ stdout_str
18
+ else
19
+ raise Ghost::Errors::CaptionError, "Error during caption download: #{stderr_str}"
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ # lib/cookies/cookies_handler.rb
2
+ require 'open3'
3
+ require_relative '../errors'
4
+
5
+ module Ghost
6
+ module Cookies
7
+ class CookiesHandler
8
+ def initialize(url, cookies_file)
9
+ @url = url
10
+ @cookies_file = cookies_file
11
+ end
12
+
13
+ def download
14
+ # Check if cookies file exists
15
+ unless File.exist?(@cookies_file)
16
+ raise Ghost::Errors::DownloadError, "Cookies file does not exist: #{@cookies_file}"
17
+ end
18
+
19
+ command = "yt-dlp --cookies #{@cookies_file} -f \"bestvideo+bestaudio/best\" --merge-output-format mp4 #{@url}"
20
+ puts "Executing download with cookies command: #{command}"
21
+
22
+ stdout_str, stderr_str, status = Open3.capture3(command)
23
+ if status.success?
24
+ puts "Download with cookies completed successfully!"
25
+ stdout_str
26
+ else
27
+ puts "Error during download with cookies: #{stderr_str}"
28
+ raise Ghost::Errors::DownloadError, "Error during download with cookies: #{stderr_str}"
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,19 @@
1
+ # lib/download/vimeo.rb
2
+ require 'open3'
3
+ require_relative '../errors'
4
+
5
+ module Ghost
6
+ module Download
7
+ class Vimeo
8
+ def initialize(url, options = {})
9
+ @url = url
10
+ end
11
+
12
+ def download
13
+ command = "yt-dlp #{@url}"
14
+ result = system(command)
15
+ raise Ghost::Errors::DownloadError, "Error during Vimeo download" unless result
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,76 @@
1
+ # lib/download/youtube.rb
2
+ require 'open3'
3
+ require_relative '../errors'
4
+
5
+ module Ghost
6
+ module Download
7
+ class Youtube
8
+ def initialize(url, options = {})
9
+ @url = url
10
+ @quality = options.fetch(:quality, "best")
11
+ @sounde = options.fetch(:sounde, true)
12
+ @progress = options.fetch(:progress, nil)
13
+ end
14
+
15
+ def download
16
+ command = build_command
17
+ # Print the command for debugging
18
+ puts "Executing command: #{command}"
19
+
20
+ if @progress
21
+ download_with_progress(command, @progress)
22
+ else
23
+ download_without_progress(command)
24
+ end
25
+ end
26
+
27
+ private
28
+
29
+ def build_command
30
+ if @sounde
31
+ # Modified command to ensure both video and audio are downloaded
32
+ "yt-dlp -f \"bestvideo+bestaudio/best\" --merge-output-format mp4 #{@url}"
33
+ else
34
+ "yt-dlp -f bestvideo #{@url}"
35
+ end
36
+ end
37
+
38
+ def download_without_progress(command)
39
+ stdout_str, stderr_str, status = Open3.capture3(command)
40
+ if status.success?
41
+ puts "Download completed successfully!"
42
+ stdout_str
43
+ else
44
+ puts "Error during download: #{stderr_str}"
45
+ raise Ghost::Errors::DownloadError, "Error during download: #{stderr_str}"
46
+ end
47
+ end
48
+
49
+ def download_with_progress(command, progress_style)
50
+ puts "Starting download with progress display..."
51
+ Open3.popen2e(command) do |stdin, stdout_err, wait_thr|
52
+ while (line = stdout_err.gets)
53
+ puts line if line.include?("Merging") # Print merging logs for debugging
54
+ if match = line.match(/(\d+\.\d+)%/)
55
+ percentage = match[1].to_f
56
+ print_progress_bar(percentage, progress_style)
57
+ end
58
+ end
59
+ exit_status = wait_thr.value
60
+ unless exit_status.success?
61
+ raise Ghost::Errors::DownloadError, "Error during download with progress"
62
+ end
63
+ puts "\nDownload completed successfully!"
64
+ end
65
+ end
66
+
67
+ def print_progress_bar(percentage, progress_style)
68
+ total_length = 20
69
+ filled_length = (percentage.to_f / 100 * total_length).round
70
+ bar = progress_style * filled_length
71
+ print "\r#{bar} %#{percentage.round(1)}"
72
+ $stdout.flush
73
+ end
74
+ end
75
+ end
76
+ end
data/lib/errors.rb ADDED
@@ -0,0 +1,13 @@
1
+ # lib/errors.rb
2
+
3
+ module Ghost
4
+ module Errors
5
+ class YlpDlpNotFounde < StandardError; end
6
+ class UrlNotFounde < StandardError; end
7
+ class BaseError < StandardError; end
8
+ class DownloadError < BaseError; end
9
+ class CaptionError < BaseError; end
10
+ class CookiesError < BaseError; end
11
+ end
12
+ end
13
+
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ghost_youtube
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Maven
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-03-08 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: "\n GhostYoutube is a pure Ruby gem that wraps the command-line
14
+ tool, making it\n easy to download YouTube videos, captions, and videos using
15
+ cookies. It is designed\n to be used in any Ruby environment (Ruby, Rails,
16
+ JRuby, CRuby, etc.).\n "
17
+ email:
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - Gemfile
23
+ - LICENSE
24
+ - README.md
25
+ - ghost_youtube.gemspec
26
+ - ghost_youtube.rb
27
+ - lib/caption/youtube_caption.rb
28
+ - lib/cookies/cookies_handler.rb
29
+ - lib/download/vimeo.rb
30
+ - lib/download/youtube.rb
31
+ - lib/errors.rb
32
+ homepage: https://github.com/Abo5/ghost_youtube
33
+ licenses:
34
+ - MIT
35
+ metadata:
36
+ allowed_push_host: https://rubygems.org
37
+ post_install_message:
38
+ rdoc_options: []
39
+ require_paths:
40
+ - lib
41
+ required_ruby_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: 2.5.0
46
+ required_rubygems_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubygems_version: 3.3.3
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: A Ruby library to download YouTube videos with audio and captions of Videos
56
+ test_files: []