youtube-rb 0.2.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 ADDED
@@ -0,0 +1,703 @@
1
+ # YoutubeRb
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.
4
+
5
+ ## Features
6
+
7
+ - 🔧 **yt-dlp Backend** - Reliable video downloads with full YouTube support
8
+ - 📹 Download full videos or audio-only
9
+ - ✂️ Extract video segments (10-60 seconds)
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.)
13
+ - 📊 Get detailed video information
14
+ - 🔧 Flexible configuration options
15
+ - 🌐 Support for cookies and authentication
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
+ ## Installation
44
+
45
+ Add this line to your application's Gemfile:
46
+
47
+ ```ruby
48
+ gem 'youtube-rb'
49
+ ```
50
+
51
+ And then execute:
52
+
53
+ $ bundle install
54
+
55
+ Or install it yourself as:
56
+
57
+ $ gem install youtube-rb
58
+
59
+ ## Requirements
60
+
61
+ ### Ruby Version
62
+
63
+ - Ruby >= 2.7.0
64
+
65
+ ### External Tools
66
+
67
+ #### yt-dlp (Strongly Recommended)
68
+
69
+ For reliable downloads and to avoid 403 errors, install yt-dlp:
70
+
71
+ ```bash
72
+ # Using pip (recommended)
73
+ pip install -U yt-dlp
74
+
75
+ # Using pipx (isolated installation)
76
+ pipx install yt-dlp
77
+
78
+ # macOS with Homebrew
79
+ brew install yt-dlp
80
+
81
+ # Or download binary from:
82
+ # https://github.com/yt-dlp/yt-dlp/releases
83
+ ```
84
+
85
+ #### FFmpeg (Optional)
86
+
87
+ Required only for:
88
+ - Audio extraction from video
89
+ - Segment extraction (10-60 second clips)
90
+ - Format conversion
91
+
92
+ ```bash
93
+ # macOS
94
+ brew install ffmpeg
95
+
96
+ # Ubuntu/Debian
97
+ sudo apt install ffmpeg
98
+
99
+ # Windows (with Chocolatey)
100
+ choco install ffmpeg
101
+ ```
102
+
103
+ **Check Installation:**
104
+
105
+ ```ruby
106
+ client = YoutubeRb::Client.new
107
+ client.check_dependencies
108
+ # => { ffmpeg: true, ytdlp: true, ytdlp_version: "2024.01.13" }
109
+ ```
110
+
111
+ ## Usage
112
+
113
+ ### Quick Start
114
+
115
+ ```ruby
116
+ require 'youtube-rb'
117
+
118
+ # 1. Simple download (automatically uses yt-dlp if available)
119
+ YoutubeRb.download('https://www.youtube.com/watch?v=VIDEO_ID',
120
+ output_path: './downloads'
121
+ )
122
+
123
+ # 2. Get video information
124
+ info = YoutubeRb.info('https://www.youtube.com/watch?v=jNQXAC9IVRw')
125
+ puts "Title: #{info.title}"
126
+ puts "Duration: #{info.duration_formatted}"
127
+ puts "Views: #{info.view_count}"
128
+
129
+ # 3. Download single segment (10-60 seconds by default)
130
+ # Requires yt-dlp to be installed
131
+ YoutubeRb.download_segment(
132
+ 'https://www.youtube.com/watch?v=VIDEO_ID',
133
+ 60, # start time in seconds
134
+ 90, # end time in seconds
135
+ output_path: './segments'
136
+ )
137
+
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
141
+ YoutubeRb.download_segments(
142
+ 'https://www.youtube.com/watch?v=VIDEO_ID',
143
+ [
144
+ { start: 0, end: 30 },
145
+ { start: 60, end: 90 },
146
+ { start: 120, end: 150 }
147
+ ],
148
+ output_path: './segments'
149
+ )
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
+ ```
176
+
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
+ ```
186
+
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:
192
+
193
+ ```ruby
194
+ client = YoutubeRb::Client.new(
195
+ cookies_file: './youtube_cookies.txt',
196
+ use_ytdlp: true
197
+ )
198
+ client.download(url)
199
+ ```
200
+
201
+ ### Common Configuration Options
202
+
203
+ ```ruby
204
+ 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
+ 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
229
+ 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...'
244
+ )
245
+ ```
246
+
247
+ ### Основные примеры
248
+
249
+ #### Создание клиента с настройками
250
+
251
+ ```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
+ # Скачать видео
261
+ client.download('https://www.youtube.com/watch?v=VIDEO_ID')
262
+ ```
263
+
264
+ #### Скачивание сегментов видео (главная функция)
265
+
266
+ Скачивание определенных интервалов видео (10-60 секунд по умолчанию):
267
+
268
+ ```ruby
269
+ client = YoutubeRb::Client.new(output_path: './segments')
270
+
271
+ # Скачать 30-секундный сегмент начиная с 1:00
272
+ output_file = client.download_segment(
273
+ 'https://www.youtube.com/watch?v=VIDEO_ID',
274
+ 60, # начало в секундах
275
+ 90 # конец в секундах
276
+ )
277
+
278
+ # С указанием имени файла
279
+ client.download_segment(
280
+ 'https://www.youtube.com/watch?v=VIDEO_ID',
281
+ 120, 150,
282
+ output_file: './my_segment.mp4'
283
+ )
284
+
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
+ # Настройка пользовательских ограничений длительности
292
+ client = YoutubeRb::Client.new(
293
+ output_path: './segments',
294
+ min_segment_duration: 5, # минимум 5 секунд
295
+ max_segment_duration: 300 # максимум 5 минут
296
+ )
297
+
298
+ client.download_segment(url, 0, 5) # ✓ Валидно с новыми настройками
299
+ client.download_segment(url, 0, 300) # ✓ Валидно (5 минут)
300
+ ```
301
+
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:
304
+
305
+ ```ruby
306
+ # Fast mode (default) - 10x faster, cuts at keyframes
307
+ client = YoutubeRb::Client.new(segment_mode: :fast)
308
+
309
+ # Precise mode - frame-accurate but slow (re-encodes video)
310
+ client = YoutubeRb::Client.new(segment_mode: :precise)
311
+ ```
312
+
313
+ See [PERFORMANCE.md](PERFORMANCE.md) for detailed performance comparison and recommendations.
314
+
315
+ #### Пакетная загрузка сегментов (новое!)
316
+
317
+ Для загрузки нескольких сегментов из одного видео используйте `download_segments`:
318
+
319
+ ```ruby
320
+ client = YoutubeRb::Client.new(output_path: './segments')
321
+
322
+ url = 'https://www.youtube.com/watch?v=VIDEO_ID'
323
+
324
+ 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
328
+ ]
329
+
330
+ # Загрузит все сегменты эффективно
331
+ 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
+ ```
336
+
337
+ **Преимущества пакетной загрузки:**
338
+
339
+ - **Оптимизация yt-dlp**: Видео скачивается через yt-dlp **один раз**, все сегменты вырезаются локально через FFmpeg
340
+ - **Быстрее в 10-100x**: Не нужно перекачивать видео для каждого сегмента
341
+ - **Экономия трафика**: Полное видео загружается один раз вместо N раз
342
+ - **Надежность**: Использует yt-dlp для обхода защиты YouTube, FFmpeg для быстрой нарезки
343
+
344
+ ```ruby
345
+ # С пользовательскими именами файлов
346
+ segments = [
347
+ { start: 0, end: 30, output_file: './intro.mp4' },
348
+ { start: 60, end: 90, output_file: './main.mp4' },
349
+ { start: 300, end: 330, output_file: './outro.mp4' }
350
+ ]
351
+
352
+ 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
+ ```
363
+
364
+ #### Скачивание субтитров
365
+
366
+ ```ruby
367
+ client = YoutubeRb::Client.new(
368
+ output_path: './downloads',
369
+ write_subtitles: true,
370
+ subtitle_langs: ['en', 'ru']
371
+ )
372
+
373
+ # При скачивании сегмента субтитры автоматически обрезаются
374
+ client.download_segment(url, 60, 90)
375
+ # Создаст: video-segment-60-90.mp4 и video-segment-60-90.en.srt
376
+
377
+ # Скачать только субтитры (без видео)
378
+ client.download_subtitles(url, langs: ['en', 'ru'])
379
+
380
+ # Проверить доступные языки субтитров
381
+ info = client.info(url)
382
+ puts info.available_subtitle_languages.join(', ')
383
+ ```
384
+
385
+ #### Извлечение аудио
386
+
387
+ ```ruby
388
+ # Извлечь аудио в MP3
389
+ client.extract_audio(url, format: 'mp3', quality: '192')
390
+
391
+ # Другие форматы
392
+ client.extract_audio(url, format: 'aac', quality: '128')
393
+ client.extract_audio(url, format: 'opus')
394
+ client.extract_audio(url, format: 'flac') # без потерь
395
+
396
+ # Или через настройки клиента
397
+ client = YoutubeRb::Client.new(
398
+ extract_audio: true,
399
+ audio_format: 'mp3',
400
+ audio_quality: '320'
401
+ )
402
+ client.download(url) # скачает только аудио
403
+ ```
404
+
405
+ #### Получение информации о видео
406
+
407
+ ```ruby
408
+ info = client.info('https://www.youtube.com/watch?v=VIDEO_ID')
409
+
410
+ puts info.title
411
+ puts info.description
412
+ puts info.duration_formatted # "01:23:45"
413
+ puts info.view_count
414
+ puts info.uploader
415
+
416
+ # Доступные форматы
417
+ info.available_formats.each do |format_id|
418
+ format = info.get_format(format_id)
419
+ puts "#{format[:format_id]}: #{format[:height]}p"
420
+ end
421
+
422
+ # Лучшее качество
423
+ best = info.best_format
424
+ video_only = info.best_video_format
425
+ audio_only = info.best_audio_format
426
+ ```
427
+
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)
474
+
475
+ For age-restricted, private, member-only videos or to bypass 403 errors:
476
+
477
+ #### Method 1: Export cookies from browser (Most Reliable)
478
+
479
+ 1. **Install browser extension to export cookies:**
480
+ - Chrome/Edge: [Get cookies.txt LOCALLY](https://chrome.google.com/webstore/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc)
481
+ - Firefox: [cookies.txt](https://addons.mozilla.org/en-US/firefox/addon/cookies-txt/)
482
+
483
+ 2. **Log into YouTube** in your browser
484
+
485
+ 3. **Export cookies** from youtube.com (Netscape format)
486
+
487
+ 4. **Use cookies in YoutubeRb:**
488
+
489
+ ```ruby
490
+ # With yt-dlp backend (recommended - automatic cookie handling)
491
+ client = YoutubeRb::Client.new(
492
+ cookies_file: './youtube_cookies.txt',
493
+ use_ytdlp: true,
494
+ verbose: true
495
+ )
496
+ 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
+ ```
505
+
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)
528
+ - 🔒 **Keep your cookies file secure** - it contains your session data
529
+ - 🔄 **Cookies expire** - re-export if you get 403 errors again
530
+ - 💡 **Use yt-dlp backend** for best cookie handling
531
+
532
+ ### Полный пример: скачивание нескольких сегментов
533
+
534
+ ```ruby
535
+ require 'youtube-rb'
536
+
537
+ client = YoutubeRb::Client.new(
538
+ output_path: './highlights',
539
+ write_subtitles: true,
540
+ subtitle_langs: ['en'],
541
+ use_ytdlp: true, # рекомендуется для надежности
542
+ cache_full_video: true # кэширование для быстрой обработки
543
+ )
544
+
545
+ url = 'https://www.youtube.com/watch?v=VIDEO_ID'
546
+
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
+ ]
553
+
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
562
+
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
+ ]
569
+
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
581
+ ```
582
+
583
+ ### Обработка ошибок
584
+
585
+ ```ruby
586
+ begin
587
+ client = YoutubeRb::Client.new
588
+ output = client.download_segment(url, 60, 90)
589
+ puts "Success: #{output}"
590
+ rescue YoutubeRb::ExtractionError => e
591
+ puts "Не удалось извлечь данные: #{e.message}"
592
+ rescue YoutubeRb::DownloadError => e
593
+ puts "Ошибка загрузки: #{e.message}"
594
+ rescue => e
595
+ puts "Ошибка: #{e.message}"
596
+ end
597
+ ```
598
+
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)
681
+
682
+ **Precise Mode (Optional):**
683
+ - 🎯 Frame-accurate cuts
684
+ - 🐌 15-second segment: ~79 seconds (187 KB/s)
685
+ - ⚙️ Requires re-encoding (CPU intensive)
686
+
687
+ ## Development
688
+
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.
690
+
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).
692
+
693
+ ## Contributing
694
+
695
+ Bug reports and pull requests are welcome on GitHub at https://github.com/Qew7/youtube-rb.
696
+
697
+ ## License
698
+
699
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
700
+
701
+ ## Credits
702
+
703
+ Inspired by [youtube-dl](https://github.com/ytdl-org/youtube-dl) and [yt-dlp](https://github.com/yt-dlp/yt-dlp).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec