or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

format-selection.mdindex.mdurl-processing.mdvideo-downloading.mdvideo-information.md

format-selection.mddocs/

0

# Format Selection

1

2

Advanced format selection utilities for choosing optimal video and audio formats based on quality, codec, and container preferences. Provides both automated selection and manual filtering capabilities.

3

4

## Capabilities

5

6

### Choose Format

7

8

Automatically selects the best format from available options based on specified criteria.

9

10

```javascript { .api }

11

/**

12

* Chooses the best format from available formats based on criteria

13

* @param {videoFormat | videoFormat[]} formats - Available formats or single format

14

* @param {chooseFormatOptions} options - Selection criteria

15

* @returns {videoFormat} - Selected format

16

* @throws {Error} - If no matching format found

17

*/

18

function chooseFormat(formats, options);

19

20

interface chooseFormatOptions {

21

quality?: string | number | string[] | number[]; // Quality preference

22

filter?: string | function; // Format filter

23

format?: videoFormat; // Specific format to use

24

}

25

```

26

27

**Usage Examples:**

28

29

```javascript

30

const info = await ytdl.getInfo(videoUrl);

31

32

// Choose highest quality format (default)

33

const format = ytdl.chooseFormat(info.formats, { quality: 'highest' });

34

35

// Choose by quality string

36

const audioFormat = ytdl.chooseFormat(info.formats, { quality: 'highestaudio' });

37

const videoFormat = ytdl.chooseFormat(info.formats, { quality: 'highestvideo' });

38

39

// Choose by itag number

40

const specificFormat = ytdl.chooseFormat(info.formats, { quality: 140 });

41

42

// Choose from multiple quality options (first available wins)

43

const format = ytdl.chooseFormat(info.formats, {

44

quality: ['highestvideo', 'highest', 140]

45

});

46

47

// Choose with filter

48

const mp4Format = ytdl.chooseFormat(info.formats, {

49

quality: 'highest',

50

filter: 'audioandvideo'

51

});

52

53

// Use custom filter function

54

const customFormat = ytdl.chooseFormat(info.formats, {

55

filter: format => format.container === 'mp4' && format.hasAudio

56

});

57

```

58

59

### Filter Formats

60

61

Filters available formats based on specific criteria, useful for examining available options before selection.

62

63

```javascript { .api }

64

/**

65

* Filters formats based on criteria

66

* @param {videoFormat | videoFormat[]} formats - Formats to filter

67

* @param {string | function} filter - Filter criteria or custom function

68

* @returns {videoFormat[]} - Filtered formats array

69

*/

70

function filterFormats(formats, filter);

71

```

72

73

**Usage Examples:**

74

75

```javascript

76

const info = await ytdl.getInfo(videoUrl);

77

78

// Filter for audio-only formats

79

const audioFormats = ytdl.filterFormats(info.formats, 'audioonly');

80

console.log(`Audio formats: ${audioFormats.length}`);

81

82

// Filter for video-only formats

83

const videoFormats = ytdl.filterFormats(info.formats, 'videoonly');

84

85

// Filter for formats with both audio and video

86

const combinedFormats = ytdl.filterFormats(info.formats, 'audioandvideo');

87

88

// Custom filter function

89

const mp4Formats = ytdl.filterFormats(info.formats, format => {

90

return format.container === 'mp4' && format.bitrate > 1000000;

91

});

92

93

// Filter for HD formats

94

const hdFormats = ytdl.filterFormats(info.formats, format => {

95

return format.height && format.height >= 720;

96

});

97

```

98

99

## Quality Options

100

101

### Predefined Quality Strings

102

103

```javascript { .api }

104

type ChooseFormatQuality =

105

| 'lowest' // Lowest quality format

106

| 'highest' // Highest quality format (default)

107

| 'highestaudio' // Best audio quality (minimizes video bitrate)

108

| 'lowestaudio' // Lowest audio quality

109

| 'highestvideo' // Best video quality (minimizes audio bitrate)

110

| 'lowestvideo'; // Lowest video quality

111

112

type VideoFormatQuality =

113

| 'tiny' | 'small' | 'medium' | 'large'

114

| 'hd720' | 'hd1080' | 'hd1440' | 'hd2160' | 'highres';

115

116

// Utility type to extend string types while preserving auto-completion

117

type ExtendString<T extends string> = T | Omit<string, T>;

118

```

119

120

**Quality Selection Behavior:**

121

122

```javascript

123

// 'highest' - Prefers formats with both audio and video, highest bitrate

124

const format = ytdl.chooseFormat(formats, { quality: 'highest' });

125

126

// 'highestaudio' - Best audio quality, worst video quality for that audio

127

const format = ytdl.chooseFormat(formats, { quality: 'highestaudio' });

128

129

// 'highestvideo' - Best video quality, worst audio quality for that video

130

const format = ytdl.chooseFormat(formats, { quality: 'highestvideo' });

131

```

132

133

### Itag-based Selection

134

135

YouTube formats are identified by itag numbers. You can specify exact formats:

136

137

```javascript

138

// Common itag examples:

139

// 18 - 360p MP4 with audio (avc1.42001E, mp4a.40.2)

140

// 140 - Audio-only M4A (mp4a.40.2) ~128kbps

141

// 137 - 1080p MP4 video-only (avc1.640028)

142

// 248 - 1080p WebM video-only (vp9)

143

144

const format = ytdl.chooseFormat(formats, { quality: 140 }); // Audio-only M4A

145

const format = ytdl.chooseFormat(formats, { quality: [137, 248, 'highest'] }); // Prefer 1080p, fallback

146

```

147

148

## Filter Options

149

150

### Predefined Filter Strings

151

152

```javascript { .api }

153

type Filter =

154

| 'audioandvideo' // Formats with both audio and video

155

| 'videoandaudio' // Same as audioandvideo

156

| 'video' // Formats containing video (may also have audio)

157

| 'videoonly' // Formats with video but no audio

158

| 'audio' // Formats containing audio (may also have video)

159

| 'audioonly' // Formats with audio but no video

160

| function; // Custom filter function

161

```

162

163

**Filter Examples:**

164

165

```javascript

166

// Get only formats with both audio and video

167

const combined = ytdl.filterFormats(formats, 'audioandvideo');

168

169

// Get video-only formats (for merging with separate audio)

170

const videoOnly = ytdl.filterFormats(formats, 'videoonly');

171

172

// Get audio-only formats

173

const audioOnly = ytdl.filterFormats(formats, 'audioonly');

174

175

// Custom filter for specific containers

176

const webmFormats = ytdl.filterFormats(formats, format => format.container === 'webm');

177

```

178

179

### Custom Filter Functions

180

181

Filter functions receive a format object and should return boolean:

182

183

```javascript { .api }

184

/**

185

* Custom filter function

186

* @param {videoFormat} format - Format to evaluate

187

* @param {number} index - Index in formats array

188

* @param {videoFormat[]} formats - Full formats array

189

* @returns {boolean} - Whether to include this format

190

*/

191

function customFilter(format, index, formats);

192

```

193

194

**Custom Filter Examples:**

195

196

```javascript

197

// Filter for high-quality MP4 formats

198

const hqMp4 = ytdl.filterFormats(formats, format => {

199

return format.container === 'mp4' &&

200

format.height >= 720 &&

201

format.hasAudio;

202

});

203

204

// Filter for formats with specific codecs

205

const h264Formats = ytdl.filterFormats(formats, format => {

206

return format.videoCodec && format.videoCodec.includes('avc1');

207

});

208

209

// Filter for live stream formats

210

const liveFormats = ytdl.filterFormats(formats, format => format.isLive);

211

212

// Filter by file size (approximate)

213

const smallFormats = ytdl.filterFormats(formats, format => {

214

const sizeEstimate = parseInt(format.contentLength) || 0;

215

return sizeEstimate < 50 * 1024 * 1024; // Under 50MB

216

});

217

```

218

219

## Format Sorting and Prioritization

220

221

Formats are automatically sorted by ytdl-core using these criteria (highest priority first):

222

223

1. **Video Encoding Quality**: H.264 > VP9 > VP8 > older codecs

224

2. **Video Bitrate**: Higher bitrate preferred

225

3. **Audio Encoding Quality**: FLAC > Opus > AAC > Vorbis > MP3 > older codecs

226

4. **Audio Bitrate**: Higher bitrate preferred

227

5. **Resolution**: Higher resolution preferred

228

229

## Advanced Selection Patterns

230

231

### Separate Audio and Video Streams

232

233

For highest quality, download separate audio and video streams and merge with ffmpeg:

234

235

```javascript

236

const info = await ytdl.getInfo(videoUrl);

237

238

// Get best video-only format

239

const videoFormat = ytdl.chooseFormat(info.formats, {

240

quality: 'highestvideo',

241

filter: 'videoonly'

242

});

243

244

// Get best audio-only format

245

const audioFormat = ytdl.chooseFormat(info.formats, {

246

quality: 'highestaudio',

247

filter: 'audioonly'

248

});

249

250

// Download both streams

251

const videoStream = ytdl.downloadFromInfo(info, { format: videoFormat });

252

const audioStream = ytdl.downloadFromInfo(info, { format: audioFormat });

253

254

// Merge with ffmpeg (external process)

255

```

256

257

### Adaptive Quality Selection

258

259

Choose formats based on available bandwidth or device capabilities:

260

261

```javascript

262

function chooseAdaptiveFormat(formats, maxBitrate) {

263

const suitableFormats = ytdl.filterFormats(formats, format => {

264

return format.hasAudio && format.hasVideo &&

265

(format.bitrate || 0) <= maxBitrate;

266

});

267

268

return ytdl.chooseFormat(suitableFormats, { quality: 'highest' });

269

}

270

271

// For mobile devices or slow connections

272

const mobileFormat = chooseAdaptiveFormat(info.formats, 1000000); // 1Mbps max

273

```

274

275

### Container-specific Selection

276

277

Choose formats based on container requirements:

278

279

```javascript

280

// Prefer MP4 for better compatibility

281

const mp4Format = ytdl.chooseFormat(info.formats, {

282

quality: 'highest',

283

filter: format => format.container === 'mp4'

284

});

285

286

// WebM for web streaming

287

const webmFormat = ytdl.chooseFormat(info.formats, {

288

quality: 'highest',

289

filter: format => format.container === 'webm'

290

});

291

```

292

293

### Live Stream Handling

294

295

Live streams require special format handling:

296

297

```javascript

298

const info = await ytdl.getInfo(liveVideoUrl);

299

300

// Filter for HLS formats (required for live streams)

301

const liveFormats = ytdl.filterFormats(info.formats, format => format.isHLS);

302

303

if (liveFormats.length > 0) {

304

const format = ytdl.chooseFormat(liveFormats, { quality: 'highest' });

305

const stream = ytdl.downloadFromInfo(info, {

306

format,

307

begin: Date.now(), // Start from current time

308

liveBuffer: 30000 // 30 second buffer

309

});

310

}

311

```

312

313

## Error Handling

314

315

Common format selection errors and solutions:

316

317

```javascript

318

try {

319

const format = ytdl.chooseFormat(info.formats, options);

320

} catch (error) {

321

if (error.message.includes('No such format found')) {

322

console.log('Requested format not available');

323

324

// Fallback to any available format

325

const fallbackFormat = ytdl.chooseFormat(info.formats, { quality: 'highest' });

326

327

// Or list available formats

328

console.log('Available formats:');

329

info.formats.forEach(f => {

330

console.log(`${f.itag}: ${f.qualityLabel} ${f.container}`);

331

});

332

}

333

}

334

```