youtube-rb 0.2.0 → 0.3.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.
data/README.md CHANGED
@@ -1,45 +1,19 @@
1
1
  # YoutubeRb
2
2
 
3
- A **Ruby library** inspired by [youtube-dl](https://github.com/ytdl-org/youtube-dl) for downloading videos, extracting video segments, and fetching subtitles from YouTube and other video platforms.
3
+ A Ruby library for downloading videos, extracting video segments, and fetching subtitles from YouTube and other video platforms. Inspired by [youtube-dl](https://github.com/ytdl-org/youtube-dl) and powered by [yt-dlp](https://github.com/yt-dlp/yt-dlp).
4
4
 
5
5
  ## Features
6
6
 
7
7
  - 🔧 **yt-dlp Backend** - Reliable video downloads with full YouTube support
8
8
  - 📹 Download full videos or audio-only
9
- - ✂️ Extract video segments (10-60 seconds)
9
+ - ✂️ Extract video segments (customizable duration limits)
10
10
  - ⚡ **Optimized batch segment downloads** - Download video once, extract multiple segments locally (10-100x faster)
11
- - 📝 Download subtitles (manual and auto-generated)
12
- - 🎵 Extract audio in various formats (mp3, aac, opus, etc.)
11
+ - 📝 Download subtitles (manual and auto-generated) with automatic trimming for segments
12
+ - 🎵 Extract audio in various formats (mp3, aac, opus, flac, etc.)
13
13
  - 📊 Get detailed video information
14
14
  - 🔧 Flexible configuration options
15
15
  - 🌐 Support for cookies and authentication
16
16
 
17
- ## Backend
18
-
19
- YoutubeRb uses **yt-dlp** as its backend for reliable video downloads:
20
-
21
- ### yt-dlp (Required for segment downloads)
22
- - Most reliable method for YouTube downloads
23
- - Handles signature decryption automatically
24
- - Works with all YouTube videos
25
- - Bypasses 403 errors
26
- - Supports authentication via cookies
27
- - **Optimized for batch processing**: Downloads video once, extracts multiple segments locally
28
-
29
- **Note**: yt-dlp is **required** for segment downloads (`download_segment` and `download_segments` methods). Full video downloads still support Pure Ruby fallback with automatic retry using yt-dlp.
30
-
31
- ## Important Notes
32
-
33
- ⚠️ **YouTube Protection**: YouTube actively protects videos with:
34
- - Signature encryption (handled by yt-dlp)
35
- - Bot detection (requires proper headers and cookies)
36
- - Rate limiting (handled automatically)
37
-
38
- 💡 **Batch Optimization**: When downloading multiple segments from the same video, the library automatically:
39
- 1. Downloads the full video **once** via yt-dlp
40
- 2. Extracts all segments locally using FFmpeg
41
- 3. Result: **10-100x faster** than downloading each segment separately
42
-
43
17
  ## Installation
44
18
 
45
19
  Add this line to your application's Gemfile:
@@ -60,13 +34,13 @@ Or install it yourself as:
60
34
 
61
35
  ### Ruby Version
62
36
 
63
- - Ruby >= 2.7.0
37
+ - Ruby >= 3.4.0
64
38
 
65
39
  ### External Tools
66
40
 
67
- #### yt-dlp (Strongly Recommended)
41
+ #### yt-dlp (Required)
68
42
 
69
- For reliable downloads and to avoid 403 errors, install yt-dlp:
43
+ YoutubeRb uses yt-dlp as its backend for downloading videos. Install yt-dlp:
70
44
 
71
45
  ```bash
72
46
  # Using pip (recommended)
@@ -82,11 +56,13 @@ brew install yt-dlp
82
56
  # https://github.com/yt-dlp/yt-dlp/releases
83
57
  ```
84
58
 
59
+ **Note**: yt-dlp is **required** for all download operations.
60
+
85
61
  #### FFmpeg (Optional)
86
62
 
87
63
  Required only for:
88
64
  - Audio extraction from video
89
- - Segment extraction (10-60 second clips)
65
+ - Segment extraction (time-based clips)
90
66
  - Format conversion
91
67
 
92
68
  ```bash
@@ -108,26 +84,22 @@ client.check_dependencies
108
84
  # => { ffmpeg: true, ytdlp: true, ytdlp_version: "2024.01.13" }
109
85
  ```
110
86
 
111
- ## Usage
112
-
113
- ### Quick Start
87
+ ## Quick Start
114
88
 
115
89
  ```ruby
116
90
  require 'youtube-rb'
117
91
 
118
- # 1. Simple download (automatically uses yt-dlp if available)
92
+ # Simple download
119
93
  YoutubeRb.download('https://www.youtube.com/watch?v=VIDEO_ID',
120
94
  output_path: './downloads'
121
95
  )
122
96
 
123
- # 2. Get video information
124
- info = YoutubeRb.info('https://www.youtube.com/watch?v=jNQXAC9IVRw')
97
+ # Get video information
98
+ info = YoutubeRb.info('https://www.youtube.com/watch?v=VIDEO_ID')
125
99
  puts "Title: #{info.title}"
126
100
  puts "Duration: #{info.duration_formatted}"
127
- puts "Views: #{info.view_count}"
128
101
 
129
- # 3. Download single segment (10-60 seconds by default)
130
- # Requires yt-dlp to be installed
102
+ # Download single segment (requires yt-dlp)
131
103
  YoutubeRb.download_segment(
132
104
  'https://www.youtube.com/watch?v=VIDEO_ID',
133
105
  60, # start time in seconds
@@ -135,9 +107,7 @@ YoutubeRb.download_segment(
135
107
  output_path: './segments'
136
108
  )
137
109
 
138
- # 4. Download multiple segments (batch processing - OPTIMIZED!)
139
- # Downloads video ONCE via yt-dlp, then extracts all segments locally
140
- # This is 10-100x faster than downloading each segment separately
110
+ # Download multiple segments (batch processing - 10-100x faster!)
141
111
  YoutubeRb.download_segments(
142
112
  'https://www.youtube.com/watch?v=VIDEO_ID',
143
113
  [
@@ -147,160 +117,60 @@ YoutubeRb.download_segments(
147
117
  ],
148
118
  output_path: './segments'
149
119
  )
150
-
151
- # 5. Download only subtitles
152
- YoutubeRb.download_subtitles(
153
- 'https://www.youtube.com/watch?v=VIDEO_ID',
154
- langs: ['en', 'ru'],
155
- output_path: './subs'
156
- )
157
- ```
158
-
159
- ### Backend Configuration
160
-
161
- ```ruby
162
- # Recommended: Enable verbose mode to see what's happening
163
- client = YoutubeRb::Client.new(verbose: true)
164
- client.download(url)
165
- # [YoutubeRb] Using yt-dlp backend for download
166
- # [YoutubeRb] Downloaded successfully with yt-dlp: ./downloads/video.mp4
167
-
168
- # Full video downloads: Pure Ruby with yt-dlp fallback (default)
169
- client = YoutubeRb::Client.new(ytdlp_fallback: true)
170
- client.download(url) # Tries Pure Ruby first, falls back to yt-dlp on 403
171
-
172
- # Segment downloads: Always use yt-dlp (required)
173
- client.download_segment(url, 10, 30) # Requires yt-dlp
174
- client.download_segments(url, segments) # Requires yt-dlp, optimized for batch
175
120
  ```
176
121
 
177
- ### Fixing 403 Errors
178
-
179
- If you encounter 403 errors:
180
-
181
- **Option 1: Use yt-dlp backend (easiest)**
182
- ```ruby
183
- client = YoutubeRb::Client.new(use_ytdlp: true)
184
- client.download(url)
185
- ```
122
+ ## Usage
186
123
 
187
- **Option 2: Export cookies from browser**
188
- 1. Install extension: [Get cookies.txt LOCALLY](https://chrome.google.com/webstore/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc) (Chrome) or [cookies.txt](https://addons.mozilla.org/firefox/addon/cookies-txt/) (Firefox)
189
- 2. Log into YouTube in your browser
190
- 3. Export cookies from youtube.com
191
- 4. Use cookies:
124
+ ### Creating a Client
192
125
 
193
126
  ```ruby
194
- client = YoutubeRb::Client.new(
195
- cookies_file: './youtube_cookies.txt',
196
- use_ytdlp: true
197
- )
198
- client.download(url)
199
- ```
127
+ require 'youtube-rb'
200
128
 
201
- ### Common Configuration Options
129
+ # Basic client
130
+ client = YoutubeRb::Client.new
202
131
 
203
- ```ruby
132
+ # Client with options
204
133
  client = YoutubeRb::Client.new(
205
- # Backend
206
- use_ytdlp: true, # Force yt-dlp (recommended)
207
- ytdlp_fallback: true, # Auto fallback on error (default)
208
- verbose: true, # Show progress logs
209
-
210
- # Segment options
211
- segment_mode: :fast, # :fast (default, 10x faster) or :precise (frame-accurate)
212
- min_segment_duration: 10, # Minimum segment duration in seconds (default: 10)
213
- max_segment_duration: 60, # Maximum segment duration in seconds (default: 60)
214
- cache_full_video: false, # Cache full video for multiple segments (default: false, auto-enabled for batch)
215
-
216
- # Output
217
134
  output_path: './downloads',
218
- output_template: '%(title)s-%(id)s.%(ext)s',
219
-
220
- # Quality
221
- quality: 'best', # or '1080p', '720p', etc.
222
-
223
- # Audio extraction
224
- extract_audio: true,
225
- audio_format: 'mp3', # mp3, aac, opus, flac, wav
226
- audio_quality: '192',
227
-
228
- # Subtitles
135
+ verbose: true,
229
136
  write_subtitles: true,
230
- subtitle_langs: ['en', 'ru'],
231
- subtitle_format: 'srt', # srt or vtt
232
-
233
- # Metadata
234
- write_info_json: true,
235
- write_thumbnail: true,
236
- write_description: true,
237
-
238
- # Authentication
239
- cookies_file: './cookies.txt',
240
-
241
- # Network
242
- retries: 10,
243
- user_agent: 'Mozilla/5.0...'
137
+ subtitle_langs: ['en']
244
138
  )
245
139
  ```
246
140
 
247
- ### Основные примеры
141
+ ### Download Methods
248
142
 
249
- #### Создание клиента с настройками
143
+ #### Full Video Download
250
144
 
251
145
  ```ruby
252
- require 'youtube-rb'
253
-
254
- client = YoutubeRb::Client.new(
255
- output_path: './downloads',
256
- write_subtitles: true,
257
- subtitle_langs: ['en', 'ru']
258
- )
259
-
260
- # Скачать видео
146
+ # Simple download
261
147
  client.download('https://www.youtube.com/watch?v=VIDEO_ID')
262
148
  ```
263
149
 
264
- #### Скачивание сегментов видео (главная функция)
265
-
266
- Скачивание определенных интервалов видео (10-60 секунд по умолчанию):
150
+ #### Single Segment Download
267
151
 
268
152
  ```ruby
269
- client = YoutubeRb::Client.new(output_path: './segments')
270
-
271
- # Скачать 30-секундный сегмент начиная с 1:00
153
+ # Download 30-second segment
272
154
  output_file = client.download_segment(
273
155
  'https://www.youtube.com/watch?v=VIDEO_ID',
274
- 60, # начало в секундах
275
- 90 # конец в секундах
156
+ 60, # start time in seconds
157
+ 90 # end time in seconds
276
158
  )
277
159
 
278
- # С указанием имени файла
160
+ # With custom output filename
279
161
  client.download_segment(
280
- 'https://www.youtube.com/watch?v=VIDEO_ID',
281
- 120, 150,
162
+ url, 120, 150,
282
163
  output_file: './my_segment.mp4'
283
164
  )
284
165
 
285
- # Ограничения по умолчанию: сегмент должен быть от 10 до 60 секунд
286
- client.download_segment(url, 0, 10) # ✓ Валидно (10 секунд)
287
- client.download_segment(url, 0, 60) # ✓ Валидно (60 секунд)
288
- client.download_segment(url, 0, 5) # ✗ Ошибка (слишком короткий)
289
- client.download_segment(url, 0, 120) # ✗ Ошибка (слишком длинный)
290
-
291
- # Настройка пользовательских ограничений длительности
166
+ # Configure segment duration limits (default: 10-60 seconds)
292
167
  client = YoutubeRb::Client.new(
293
- output_path: './segments',
294
- min_segment_duration: 5, # минимум 5 секунд
295
- max_segment_duration: 300 # максимум 5 минут
168
+ min_segment_duration: 5, # minimum 5 seconds
169
+ max_segment_duration: 300 # maximum 5 minutes
296
170
  )
297
-
298
- client.download_segment(url, 0, 5) # ✓ Валидно с новыми настройками
299
- client.download_segment(url, 0, 300) # ✓ Валидно (5 минут)
300
171
  ```
301
172
 
302
- **⚡ Performance Note**: By default, segments use **fast mode** (10x faster).
303
- Cuts may be off by a few seconds due to keyframe positions. For frame-accurate cuts:
173
+ **Performance Note**: By default, segments use **fast mode** (10x faster). Cuts may be off by a few seconds due to keyframe positions. For frame-accurate cuts:
304
174
 
305
175
  ```ruby
306
176
  # Fast mode (default) - 10x faster, cuts at keyframes
@@ -310,39 +180,23 @@ client = YoutubeRb::Client.new(segment_mode: :fast)
310
180
  client = YoutubeRb::Client.new(segment_mode: :precise)
311
181
  ```
312
182
 
313
- See [PERFORMANCE.md](PERFORMANCE.md) for detailed performance comparison and recommendations.
314
-
315
- #### Пакетная загрузка сегментов (новое!)
183
+ #### Batch Segment Download
316
184
 
317
- Для загрузки нескольких сегментов из одного видео используйте `download_segments`:
185
+ For downloading multiple segments from one video, use `download_segments` for optimal performance:
318
186
 
319
187
  ```ruby
320
- client = YoutubeRb::Client.new(output_path: './segments')
321
-
322
188
  url = 'https://www.youtube.com/watch?v=VIDEO_ID'
323
189
 
324
190
  segments = [
325
- { start: 0, end: 30 }, # Первые 30 секунд
326
- { start: 60, end: 90 }, # 1:00 - 1:30
327
- { start: 120, end: 150 } # 2:00 - 2:30
191
+ { start: 0, end: 30 },
192
+ { start: 60, end: 90 },
193
+ { start: 120, end: 150 }
328
194
  ]
329
195
 
330
- # Загрузит все сегменты эффективно
331
196
  output_files = client.download_segments(url, segments)
332
- # => ["./segments/video-segment-0-30.mp4", "./segments/video-segment-60-90.mp4", ...]
333
-
334
- puts "Downloaded #{output_files.size} segments"
335
- ```
197
+ # => ["./segments/video-segment-0-30.mp4", ...]
336
198
 
337
- **Преимущества пакетной загрузки:**
338
-
339
- - **Оптимизация yt-dlp**: Видео скачивается через yt-dlp **один раз**, все сегменты вырезаются локально через FFmpeg
340
- - **Быстрее в 10-100x**: Не нужно перекачивать видео для каждого сегмента
341
- - **Экономия трафика**: Полное видео загружается один раз вместо N раз
342
- - **Надежность**: Использует yt-dlp для обхода защиты YouTube, FFmpeg для быстрой нарезки
343
-
344
- ```ruby
345
- # С пользовательскими именами файлов
199
+ # With custom filenames
346
200
  segments = [
347
201
  { start: 0, end: 30, output_file: './intro.mp4' },
348
202
  { start: 60, end: 90, output_file: './main.mp4' },
@@ -350,59 +204,56 @@ segments = [
350
204
  ]
351
205
 
352
206
  client.download_segments(url, segments)
353
-
354
- # Явное управление кэшированием (по умолчанию включено для batch)
355
- client = YoutubeRb::Client.new(
356
- output_path: './segments',
357
- cache_full_video: false # отключить кэш (медленнее)
358
- )
359
-
360
- # Или переопределить при вызове
361
- client.download_segments(url, segments, cache_full_video: true)
362
207
  ```
363
208
 
364
- #### Скачивание субтитров
209
+ **Benefits of Batch Processing:**
210
+ - **10-100x faster**: Video downloaded via yt-dlp once, all segments extracted locally with FFmpeg
211
+ - **Bandwidth savings**: Full video loaded once instead of N times
212
+ - **Reliability**: Uses yt-dlp to bypass YouTube protection
213
+
214
+ #### Subtitles Download
365
215
 
366
216
  ```ruby
217
+ # Download subtitles with video
367
218
  client = YoutubeRb::Client.new(
368
- output_path: './downloads',
369
219
  write_subtitles: true,
370
220
  subtitle_langs: ['en', 'ru']
371
221
  )
222
+ client.download(url)
372
223
 
373
- # При скачивании сегмента субтитры автоматически обрезаются
374
- client.download_segment(url, 60, 90)
375
- # Создаст: video-segment-60-90.mp4 и video-segment-60-90.en.srt
376
-
377
- # Скачать только субтитры (без видео)
224
+ # Download subtitles only
378
225
  client.download_subtitles(url, langs: ['en', 'ru'])
379
226
 
380
- # Проверить доступные языки субтитров
227
+ # Check available subtitle languages
381
228
  info = client.info(url)
382
229
  puts info.available_subtitle_languages.join(', ')
230
+
231
+ # Subtitles are automatically trimmed for segments
232
+ client.download_segment(url, 60, 90)
233
+ # Creates: video-segment-60-90.mp4 and video-segment-60-90.en.srt
383
234
  ```
384
235
 
385
- #### Извлечение аудио
236
+ #### Audio Extraction
386
237
 
387
238
  ```ruby
388
- # Извлечь аудио в MP3
239
+ # Extract audio in MP3
389
240
  client.extract_audio(url, format: 'mp3', quality: '192')
390
241
 
391
- # Другие форматы
242
+ # Other formats
392
243
  client.extract_audio(url, format: 'aac', quality: '128')
393
244
  client.extract_audio(url, format: 'opus')
394
- client.extract_audio(url, format: 'flac') # без потерь
245
+ client.extract_audio(url, format: 'flac') # lossless
395
246
 
396
- # Или через настройки клиента
247
+ # Or configure client to extract audio by default
397
248
  client = YoutubeRb::Client.new(
398
249
  extract_audio: true,
399
250
  audio_format: 'mp3',
400
251
  audio_quality: '320'
401
252
  )
402
- client.download(url) # скачает только аудио
253
+ client.download(url) # Downloads audio only
403
254
  ```
404
255
 
405
- #### Получение информации о видео
256
+ ### Video Information
406
257
 
407
258
  ```ruby
408
259
  info = client.info('https://www.youtube.com/watch?v=VIDEO_ID')
@@ -413,70 +264,25 @@ puts info.duration_formatted # "01:23:45"
413
264
  puts info.view_count
414
265
  puts info.uploader
415
266
 
416
- # Доступные форматы
267
+ # Available formats
417
268
  info.available_formats.each do |format_id|
418
269
  format = info.get_format(format_id)
419
270
  puts "#{format[:format_id]}: #{format[:height]}p"
420
271
  end
421
272
 
422
- # Лучшее качество
273
+ # Best quality formats
423
274
  best = info.best_format
424
275
  video_only = info.best_video_format
425
276
  audio_only = info.best_audio_format
426
277
  ```
427
278
 
428
- ### Настройки (Options)
429
-
430
- ```ruby
431
- client = YoutubeRb::Client.new(
432
- # Основные
433
- output_path: './downloads',
434
- output_template: '%(title)s-%(id)s.%(ext)s',
435
- format: 'best',
436
- quality: 'best',
437
-
438
- # Сегменты
439
- segment_mode: :fast, # :fast (быстро) или :precise (точно)
440
- min_segment_duration: 10, # минимальная длительность сегмента (секунды)
441
- max_segment_duration: 60, # максимальная длительность сегмента (секунды)
442
- cache_full_video: false, # кэшировать полное видео для нескольких сегментов
443
-
444
- # Субтитры
445
- write_subtitles: true,
446
- subtitle_format: 'srt', # srt, vtt, ass
447
- subtitle_langs: ['en', 'ru'],
448
-
449
- # Аудио
450
- extract_audio: false,
451
- audio_format: 'mp3', # mp3, aac, opus, flac, wav
452
- audio_quality: '192',
453
-
454
- # Файловая система
455
- no_overwrites: true, # не перезаписывать файлы
456
- continue_download: true, # продолжать прерванные загрузки
457
- write_description: true,
458
- write_info_json: true,
459
- write_thumbnail: true,
460
-
461
- # Сеть
462
- rate_limit: '1M', # ограничение скорости
463
- retries: 10,
464
- user_agent: 'Mozilla/5.0...',
465
-
466
- # Аутентификация (если нужна)
467
- cookies_file: './cookies.txt',
468
- username: 'user',
469
- password: 'pass'
470
- )
471
- ```
472
-
473
- ### Authentication and Cookies (Bypassing 403 Errors)
279
+ ### Authentication and Cookies
474
280
 
475
- For age-restricted, private, member-only videos or to bypass 403 errors:
281
+ For age-restricted, private, or member-only videos, or to bypass 403 errors:
476
282
 
477
- #### Method 1: Export cookies from browser (Most Reliable)
283
+ #### Export Cookies from Browser (Most Reliable)
478
284
 
479
- 1. **Install browser extension to export cookies:**
285
+ 1. **Install browser extension:**
480
286
  - Chrome/Edge: [Get cookies.txt LOCALLY](https://chrome.google.com/webstore/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc)
481
287
  - Firefox: [cookies.txt](https://addons.mozilla.org/en-US/firefox/addon/cookies-txt/)
482
288
 
@@ -487,100 +293,92 @@ For age-restricted, private, member-only videos or to bypass 403 errors:
487
293
  4. **Use cookies in YoutubeRb:**
488
294
 
489
295
  ```ruby
490
- # With yt-dlp backend (recommended - automatic cookie handling)
491
296
  client = YoutubeRb::Client.new(
492
297
  cookies_file: './youtube_cookies.txt',
493
- use_ytdlp: true,
494
298
  verbose: true
495
299
  )
496
300
  client.download('https://www.youtube.com/watch?v=VIDEO_ID')
497
-
498
- # Pure Ruby backend also supports cookies
499
- client = YoutubeRb::Client.new(
500
- cookies_file: './youtube_cookies.txt',
501
- use_ytdlp: false,
502
- ytdlp_fallback: true # Falls back to yt-dlp on 403
503
- )
504
301
  ```
505
302
 
506
- #### Method 2: Let yt-dlp extract cookies from browser (Easiest)
507
-
508
- yt-dlp can directly read cookies from your browser:
509
-
510
- ```bash
511
- # First, ensure browser is closed or use the right browser
512
- yt-dlp --cookies-from-browser chrome <URL>
513
- ```
514
-
515
- **Note:** This feature requires specific system dependencies and may not work on all platforms. Cookie file export (Method 1) is more reliable.
516
-
517
- #### Cookie file format example (Netscape)
518
-
519
- ```
520
- # Netscape HTTP Cookie File
521
- .youtube.com TRUE / TRUE 0 CONSENT YES+
522
- .youtube.com TRUE / FALSE 1735689600 VISITOR_INFO1_LIVE xxxxx
523
- ```
524
-
525
- #### Important Notes
526
-
527
- - ⚠️ **Username/password authentication** is NOT supported (YouTube uses OAuth)
303
+ **Important Notes:**
528
304
  - 🔒 **Keep your cookies file secure** - it contains your session data
529
305
  - 🔄 **Cookies expire** - re-export if you get 403 errors again
530
- - 💡 **Use yt-dlp backend** for best cookie handling
531
306
 
532
- ### Полный пример: скачивание нескольких сегментов
307
+ ## Configuration Options
533
308
 
534
309
  ```ruby
535
- require 'youtube-rb'
536
-
537
310
  client = YoutubeRb::Client.new(
538
- output_path: './highlights',
311
+ # Logging
312
+ verbose: true, # Show progress logs
313
+
314
+ # Output
315
+ output_path: './downloads',
316
+ output_template: '%(title)s-%(id)s.%(ext)s',
317
+ no_overwrites: true, # Don't overwrite existing files
318
+ continue_download: true, # Resume interrupted downloads
319
+
320
+ # Quality
321
+ quality: 'best', # or '1080p', '720p', etc.
322
+ format: 'best',
323
+
324
+ # Segment Options
325
+ segment_mode: :fast, # :fast (10x faster) or :precise (frame-accurate)
326
+ min_segment_duration: 10, # Minimum segment duration in seconds
327
+ max_segment_duration: 60, # Maximum segment duration in seconds
328
+ cache_full_video: false, # Cache full video for multiple segments (auto-enabled for batch)
329
+
330
+ # Audio Extraction
331
+ extract_audio: true,
332
+ audio_format: 'mp3', # mp3, aac, opus, flac, wav
333
+ audio_quality: '192',
334
+
335
+ # Subtitles
539
336
  write_subtitles: true,
540
- subtitle_langs: ['en'],
541
- use_ytdlp: true, # рекомендуется для надежности
542
- cache_full_video: true # кэширование для быстрой обработки
337
+ subtitle_langs: ['en', 'ru'],
338
+ subtitle_format: 'srt', # srt, vtt, or ass
339
+
340
+ # Metadata
341
+ write_info_json: true,
342
+ write_thumbnail: true,
343
+ write_description: true,
344
+
345
+ # Authentication
346
+ cookies_file: './cookies.txt',
347
+
348
+ # Network
349
+ retries: 10,
350
+ rate_limit: '1M',
351
+ user_agent: 'Mozilla/5.0...'
543
352
  )
353
+ ```
544
354
 
545
- url = 'https://www.youtube.com/watch?v=VIDEO_ID'
355
+ ## Troubleshooting
546
356
 
547
- # Вариант 1: Пакетная загрузка (рекомендуется, быстрее)
548
- segments = [
549
- { start: 0, end: 30, output_file: './highlights/intro.mp4' },
550
- { start: 120, end: 150, output_file: './highlights/main.mp4' },
551
- { start: 300, end: 330, output_file: './highlights/conclusion.mp4' }
552
- ]
357
+ ### 403 Errors or Bot Detection
553
358
 
554
- begin
555
- output_files = client.download_segments(url, segments)
556
- output_files.each_with_index do |file, i|
557
- puts "✓ Segment #{i+1}: #{file}"
558
- end
559
- rescue => e
560
- puts "✗ Error: #{e.message}"
561
- end
359
+ **Export cookies from browser:**
360
+ ```ruby
361
+ client = YoutubeRb::Client.new(
362
+ cookies_file: './youtube_cookies.txt'
363
+ )
364
+ client.download(url)
365
+ ```
562
366
 
563
- # Вариант 2: По одному (если нужен контроль над каждым сегментом)
564
- segments_old_way = [
565
- { start: 0, end: 30, name: 'intro' },
566
- { start: 120, end: 150, name: 'main' },
567
- { start: 300, end: 330, name: 'conclusion' }
568
- ]
367
+ ### No Formats Found / Video Unavailable
569
368
 
570
- segments_old_way.each do |seg|
571
- begin
572
- output = client.download_segment(
573
- url, seg[:start], seg[:end],
574
- output_file: "./highlights/#{seg[:name]}.mp4"
575
- )
576
- puts "✓ #{seg[:name]}: #{output}"
577
- rescue => e
578
- puts "✗ #{seg[:name]}: #{e.message}"
579
- end
580
- end
369
+ - Export cookies from authenticated browser session
370
+ - Check if video is available in your region
371
+ - Verify the video is public and not deleted
372
+
373
+ ### FFmpeg Not Found
374
+
375
+ For segment downloads, FFmpeg is required:
376
+ ```bash
377
+ which ffmpeg # check
378
+ brew install ffmpeg # install (macOS)
581
379
  ```
582
380
 
583
- ### Обработка ошибок
381
+ ## Error Handling
584
382
 
585
383
  ```ruby
586
384
  begin
@@ -588,107 +386,29 @@ begin
588
386
  output = client.download_segment(url, 60, 90)
589
387
  puts "Success: #{output}"
590
388
  rescue YoutubeRb::ExtractionError => e
591
- puts "Не удалось извлечь данные: #{e.message}"
389
+ puts "Failed to extract data: #{e.message}"
592
390
  rescue YoutubeRb::DownloadError => e
593
- puts "Ошибка загрузки: #{e.message}"
391
+ puts "Download error: #{e.message}"
392
+ rescue YoutubeRb::ValidationError => e
393
+ puts "Validation error: #{e.message}"
594
394
  rescue => e
595
- puts "Ошибка: #{e.message}"
395
+ puts "Error: #{e.message}"
596
396
  end
597
397
  ```
598
398
 
599
- ## Архитектура
600
-
601
- - **Client** - Основной интерфейс для всех операций
602
- - **Options** - Управление конфигурацией
603
- - **Extractor** - Извлекает информацию о видео из HTML/JSON YouTube
604
- - **VideoInfo** - Представляет метаданные видео
605
- - **Downloader** - Обрабатывает загрузку видео и субтитров через HTTP
606
-
607
- ## Comparison with youtube-dl
608
-
609
- This gem provides a Ruby-native API inspired by youtube-dl but designed as a library rather than a command-line tool:
610
-
611
- | Feature | youtube-dl | youtube-rb |
612
- |---------|-----------|------------|
613
- | Language | Python CLI | Ruby Library |
614
- | Implementation | Python executable | Pure Ruby gem |
615
- | Usage | Command line | Programmatic API |
616
- | Dependencies | Python + ffmpeg | Ruby + ffmpeg (optional) |
617
- | Segment Download | Manual with ffmpeg | Built-in method |
618
- | Subtitle Trimming | Manual | Automatic for segments |
619
- | Configuration | CLI arguments | Ruby objects |
620
- | Bot Detection | Less common | May require cookies |
621
-
622
- ## Решение проблем
623
-
624
- ### Ошибка "LOGIN_REQUIRED" или блокировка бота
625
-
626
- If you're getting 403 errors or bot detection:
627
-
628
- 1. **Use yt-dlp backend (most reliable)**:
629
- ```ruby
630
- client = YoutubeRb::Client.new(use_ytdlp: true, verbose: true)
631
- client.download(url)
632
- ```
633
-
634
- 2. **Export and use cookies from authenticated browser session**:
635
- ```ruby
636
- client = YoutubeRb::Client.new(
637
- cookies_file: './youtube_cookies.txt',
638
- use_ytdlp: true
639
- )
640
- ```
641
-
642
- 3. **Enable fallback mode** (default):
643
- ```ruby
644
- client = YoutubeRb::Client.new(ytdlp_fallback: true)
645
- # Tries pure Ruby first, falls back to yt-dlp on 403
646
- ```
647
-
648
- 4. **Add delays between requests**:
649
- ```ruby
650
- videos.each do |url|
651
- client.download(url)
652
- sleep 2
653
- end
654
- ```
655
-
656
- ### No formats found / Video unavailable
657
-
658
- Try:
659
- - Use yt-dlp backend: `YoutubeRb::Client.new(use_ytdlp: true)`
660
- - Export cookies from authenticated browser session
661
- - Check if video is available in your region
662
- - Verify the video is public and not deleted
663
- - Check yt-dlp directly: `yt-dlp --cookies ./cookies.txt <URL>`
664
-
665
- ### FFmpeg не найден
666
-
667
- Для работы с сегментами нужен FFmpeg:
668
- ```bash
669
- which ffmpeg # проверить
670
- brew install ffmpeg # установить (macOS)
671
- ```
672
-
673
- ## Performance
674
-
675
- Segment downloads are optimized for speed by default, using stream copy instead of re-encoding.
676
-
677
- **Fast Mode (Default):**
678
- - ⚡ 10x faster downloads
679
- - 📦 15-second segment: ~9 seconds (1.88 MB/s)
680
- - ⚠️ Cuts at keyframes (may be ±2-5 seconds off)
399
+ ## Architecture
681
400
 
682
- **Precise Mode (Optional):**
683
- - 🎯 Frame-accurate cuts
684
- - 🐌 15-second segment: ~79 seconds (187 KB/s)
685
- - ⚙️ Requires re-encoding (CPU intensive)
401
+ - **Client** - Main interface for all operations
402
+ - **Options** - Configuration management
403
+ - **VideoInfo** - Represents video metadata
404
+ - **Downloader** - Handles video downloads
405
+ - **YtdlpWrapper** - Wrapper for yt-dlp backend (primary download engine)
686
406
 
687
407
  ## Development
688
408
 
689
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
409
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt.
690
410
 
691
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
411
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`.
692
412
 
693
413
  ## Contributing
694
414
 
@@ -700,4 +420,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
700
420
 
701
421
  ## Credits
702
422
 
703
- Inspired by [youtube-dl](https://github.com/ytdl-org/youtube-dl) and [yt-dlp](https://github.com/yt-dlp/yt-dlp).
423
+ Inspired by [youtube-dl](https://github.com/ytdl-org/youtube-dl) and powered by [yt-dlp](https://github.com/yt-dlp/yt-dlp).