gotube

package module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 18, 2020 License: MIT Imports: 19 Imported by: 0

README

Gotube

go mod version goreportcard godoc license

Gotube is a lightweight yet reliable Go library (and command-line utility) for interacting with YouTube videos. You can retrieve their information, streams and captions, as well as downloading them.

Quickstart

video, err := gotube.NewVideo("https://www.youtube.com/watch?v=9vc-I9rvGsw", true)
stream := video.Streams().Videos().Best() // <- obtain the highest quality video stream
path, err := stream.Download("./videos/", "", true,
    func(total int64) {
        fmt.Println("Total:", total)
    },
    func(written int64) {
        fmt.Print(written, "\r")
    },
)
// (errors are ignored for better readability)

Features

  • 🚸 Easy to use, fast and lightweight (CLI included)
  • ✨ Minimalist-designed library interface
  • 📞 Custom callbacks for downloading streams (onStart and onProgress)
  • 🔍 Powerful stream querying methods
  • 🎼 Support for both progressive and adaptive streams
  • 💨 Fast downloading (parallel download with the file splitted into parts)
  • 📑 Ability to extract detailed video information (including thumbnails)
  • 📄 Support for retrieving video captions and save them in WebVTT format
  • 🔞 Support age-restricted videos
  • 🔒 Support for encrypted videos
  • 📦 Without external dependencies (except for the CLI)

Installation

Get Prebuilt Binaries

Please go to the releases page for downloads.

Go Get

Use this method if you wish to use gotube as a library as well as its command-line program.

Please make sure you have Go 1.13+ installed in your machine.

$ go get -u github.com/a1phat0ny/gotube/...

Build From Source

Please make sure you have Go 1.13+ installed in your machine.

$ git clone https://github.com/a1phat0ny/gotube.git
$ cd gotube
$ go build cmd/gotubedl/main.go
# then run ./main to get started

Usage

The fastest way to get started is to learn by examples!

Don't forget to import the package first!

import "github.com/a1phat0ny/gotube"

Let's begin by getting the video!

// You can either use the url of the video ...
video, err := gotube.NewVideo("https://www.youtube.com/watch?v=9vc-I9rvGsw", true)
// or you can simply use the video id ...
video, err := gotube.NewVideo("9vc-I9rvGsw", true)

If the second parameter (preinit) is set to false, you will need to call Initialize() afterwards before accessing any fields and methods.

For more information, visit the documentations.

Obtaining Streams

streams := video.Streams() // --> Streams ([]Stream)
Selecting a single stream

These methods return a single Stream.

streams.First() // select the first stream (index=0)
streams.Last() // select the last stream (index=-1)
streams.Itag(238) // select by itag

You may need to do type assertion afterwards to handle different types of streams (VideoStream vs AudioStream).

Since Stream is an interface, you cannot access the fields of the implemented struct (either VideoStream or AudioStream) directly. Therefore, here is where Stream.Metadata() comes into place.

Stream.Metadata() marshals the fields of the stream itself into a map[interface{}] (the keys are marshaled according to the fields' JSON tags) so that you can access the fields of the stream. However you must be very careful while using this method, as there are fields that only exists in VideoStream but not AudioStream, vice versa.

Sorting streams

The Streams.Sort() method accepts a less parameter, which is a func(Stream, Stream) bool.

It is almost identical with the less functions of Go's sort package.

// Sort streams by their filesize in ascending order
streams = streams.Sort(func (stream1, stream2 Stream) bool {
    return stream1.Metadata()["file_size"].(int64) < stream2.Metadata()["file_size"].(int64)
})
Filtering streams
// only keep .mp4 format video streams
streams = streams.Filter(func (stream Stream) bool {
    return stream.Subtype() == "mp4"
})
// ...or you can simply use this shorthand method
streams = streams.Subtype("mp4")
// To get video streams only,
vstreams := streams.Videos() // --> VideoStreams

// To get video streams that also has audio,
avstreams := streams.Videos().WithAudio() // --> VideoStreams

// To get audio streams only,
astreams := streams.Audios() // --> AudioStreams

Selecting the best stream

// To get highest resolution video stream,
streams.Videos().Best() // --> *VideoStream or nil

// To get highest resolution video stream that also has audio,
streams.Videos().WithAudio().Best() // --> *VideoStream or nil

// To get highest bitrate audio stream,
streams.Audios().Best() // --> *AudioStream or nil

Downloading stream

path, err := stream.Download("../music", "favourite_song", true,
    func(total int64) {
        fmt.Println("Total", total)
    },
    func(written int64) {
        fmt.Print(written, "\r")
    },
) // path: /Users/tony/music/favourite_song.mp4

Obtaining Captions

captions := video.Captions() // --> Captions ([]*Caption)

Caption is a struct, not an interface

Selecting by language code

caption := captions.LanguageCode("en")

This is currently the only available method of the Captions type.

Saving to disk

path, err := caption.Save("../captions", "english", true)
fmt.Println(path) // path: /Users/tony/captions/english.vtt

Handling Errors

Check if the error returned implements the gotube.Error interface.

if e, is := err.(gotube.Error); is {
    fmt.Println(e.Name())
}

Command-line Interface

usage: gotubedl [<flags>] [<idurl>]

A command-line YouTube video downloader powered by gotube.

Flags:
  -h, --help               Show context-sensitive help.
  -s, --streams            List all available streams of the video.
  -c, --captions           List all available captions of the video.
  -i, --itag=ITAG          Download stream by the given itag.
  -b, --best=BEST          Download best quality stream of the given type. [a | v | av | a+v]
  -l, --lang=LANG          Download caption with the given language code.
  -d, --dest=DEST          Destination output directory.
  -f, --filename=FILENAME  Destination video filename.
  -n, --no-prefer-mp4      Toggle preference to mp4 formats.
  -o, --overwrite          Overwrite existing file that has the same filename.
      --version            Show application version.

Args:
  [<idurl>]  Target video ID or video URL.

Download the best audio stream

$ gotubedl "https://www.youtube.com/watch?v=9vc-I9rvGsw" -b a

Download the best video stream

$ gotubedl "https://www.youtube.com/watch?v=9vc-I9rvGsw" -b v

Download the best video stream (with audio)

$ gotubedl "https://www.youtube.com/watch?v=9vc-I9rvGsw" -b av

Download the best stream (remuxing)

When using a+v, both the best audio stream and the best video stream will be downloaded. Then, gotubedl will execute ffmpeg to combine the audio and the video into a single video file.

If no-prefer-mp4 is not specified, the audio stream and video stream chosen will be in mp4 formats, and the final output video file will result a mp4 as well.

Otherwise, the audio stream and video stream chosen may be in different formats and the final output video file will result in a mkv in this case.

$ gotubedl "https://www.youtube.com/watch?v=9vc-I9rvGsw" -b a+v

TODOs

  • Add support for playlists
  • Fix support for age-restricted videos

Contributing

If you are interested in this project,

  1. feel free to open an issue for bug or feature request.
  2. and you are a Go developer, feel free to submit a pull request to help improve this project.

Any help you can provide would be greatly appreciated!!

Credits

This project is inspired by @nficano's pytube.


Made with ♥︎ by a1phat0ny
MIT © 2020 Tony Chan

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AudioStream

type AudioStream struct {
	FileSize       int64             `json:"file_size"`
	MimeType       string            `json:"mime_type"`
	Codec          string            `json:"codec"`
	Quality        data.AudioQuality `json:"quality"`
	Bitrate        int64             `json:"bitrate"`
	AverageBitrate int64             `json:"average_bitrate"`
	SampleRate     int64             `json:"sample_rate"`
	Channels       int               `json:"channels"`
	Expiration     time.Time         `json:"expiration"`
	// contains filtered or unexported fields
}

AudioStream represents a stream of type 'audio'.

func (*AudioStream) Download

func (stream *AudioStream) Download(destdir, filename string, overwrite bool, onStart func(total int64), onProgress func(written int64)) (path string, err error)

Download downloads the content of this stream and saves it to a file in the local machine. If `destdir` is empty, it defaults to the current directory. If `filename` is empty, it defaults to the name of this stream (i.e. `Name()`). If `overwrite` is true, it will overwrite the existing file of the same filename, skip downloading otherwise. `onProgress` is called whenever `Write()` occurrs, with the total amount of written bytes provided as parameter.

func (*AudioStream) GetDownloadURL

func (stream *AudioStream) GetDownloadURL() (string, error)

GetDownloadURL gets the decrypted URL to the direct source of this stream that can be used for downloading.

func (*AudioStream) Itag

func (stream *AudioStream) Itag() int

Itag returns the itag of this stream.

func (*AudioStream) Metadata

func (stream *AudioStream) Metadata() map[string]interface{}

Metadata returns a map consisting all the fields of this stream.

func (*AudioStream) Name

func (stream *AudioStream) Name() string

Name returns the name of this stream.

func (*AudioStream) ParentVideo

func (stream *AudioStream) ParentVideo() *Video

ParentVideo returns a pointer to the video object that this stream belongs to.

func (*AudioStream) Subtype

func (stream *AudioStream) Subtype() string

Subtype returns the subtype (extension) gotten from mime type of this stream.

func (*AudioStream) Type

func (stream *AudioStream) Type() string

Type returns the type of this stream. (audio)

type AudioStreams

type AudioStreams []*AudioStream

AudioStreams represents a sequence of streams of type 'audio'.

func (AudioStreams) Best

func (streams AudioStreams) Best() *AudioStream

Best returns the `AudioStream` object with the highest overall bitrate.

func (AudioStreams) First

func (streams AudioStreams) First() *AudioStream

First returns the first `AudioStream` object in this `AudioStreams`.

func (AudioStreams) Last

func (streams AudioStreams) Last() *AudioStream

Last returns the last `AudioStream` object in this `AudioStreams`.

func (AudioStreams) Worst

func (streams AudioStreams) Worst() *AudioStream

Worst returns the `AudioStream` object with the lowest overall bitrate.

type Caption

type Caption struct {
	URL          string
	Name         string
	LanguageCode string
	// contains filtered or unexported fields
}

Caption represents a caption of a YouTube video.

func (*Caption) GetContent

func (caption *Caption) GetContent() (string, error)

GetContent retrieves the content of this caption (most likely in xml format).

func (*Caption) GetWebVTT

func (caption *Caption) GetWebVTT() (string, error)

GetWebVTT first retrieves the content of this caption by calling `GetContent()` then converts and returns it in WebVTT format.

func (*Caption) Save

func (caption *Caption) Save(destdir, filename string, webvtt bool) (finalpath string, err error)

Save downloads the content of this caption and saves it to a file in the local machine. If `destdir` is empty, it defaults to the current directory. If `filename` is empty, it defaults to the name of this caption. If `webvtt` is true, it saves the content in a WebVTT (.vtt) format file.

type Captions

type Captions []*Caption

Captions represents a sequence of captions.

func (Captions) LanguageCode

func (captions Captions) LanguageCode(lc string) *Caption

LanguageCode returns the `Caption` of the given language code.

type Error

type Error interface {
	Name() string
	Error() string
}

type Stream

type Stream interface {
	ParentVideo() *Video
	Type() string
	Subtype() string
	Name() string
	Itag() int
	Metadata() map[string]interface{}
	GetDownloadURL() (string, error)
	Download(destdir, filename string, overwrite bool, onStart func(int64), onProgress func(int64)) (string, error)
}

Stream is an interface which is implemented by `VideoStream` and `AudioStream`.

type Streams

type Streams []Stream

Streams represents a generic sequence of streams which can be of type 'video' or type 'audio'.

func (Streams) Audios

func (streams Streams) Audios() (audioStreams AudioStreams)

Audios returns a `AudioStreams` (i.e. streams of type 'audio' only) from this `Streams`.

func (Streams) Filter

func (streams Streams) Filter(f func(int, Stream) bool) (results Streams)

Filter returns a filtered copy of this `Streams` according to the conditions of `f`. If `f` returns true, keep the stream, remove otherwise.

func (Streams) First

func (streams Streams) First() Stream

First returns the first `Stream` object in this `Streams`.

func (Streams) Itag

func (streams Streams) Itag(itag int) Stream

Itag returns the `Stream` of the given itag.

func (Streams) Last

func (streams Streams) Last() Stream

Last returns the last `Stream` object in this `Streams`.

func (Streams) Sort

func (streams Streams) Sort(less func(Stream, Stream) bool) (results Streams)

Sort returns a sorted copy of this `Streams` according to the conditions of `less` (works the same with the sort package).

func (Streams) Subtype

func (streams Streams) Subtype(subtype string) Streams

Subtype returns a copy of this `Streams` of the given subtype.

func (Streams) Videos

func (streams Streams) Videos() (videoStreams VideoStreams)

Videos returns a `VideoStreams` (i.e. streams of type 'video' only) from this `Streams`.

type Video

type Video struct {
	*VideoInfo

	ID              string
	WatchURL        string
	EmbedURL        string
	IsAgeRestricted bool
	// contains filtered or unexported fields
}

Video represents a YouTube video object, carrying the information, streams and captions of the video.

func NewVideo

func NewVideo(idurl string, preinit bool) (vid *Video, err error)

NewVideo returns a new video object of the given `idurl` (can be one of video id or video url). If `preinit` is true, all necessary HTTP requests will be done and data will be fetched on initialization. Otherwise, you will need to call `Initialize()` yourself before accessing any fields of this video object.

func (*Video) Captions

func (video *Video) Captions() Captions

Captions retrieves all the available captions that belong to this video.

func (*Video) Initialize

func (video *Video) Initialize() (err error)

Initialize performs all necessary HTTP requests and descrambles the fetched data.

func (*Video) Streams

func (video *Video) Streams() Streams

Streams retrieves all the available streams that belong to this video.

type VideoInfo

type VideoInfo struct {
	Title           string
	Description     string
	Keywords        []string
	Category        string
	Duration        int
	Views           int
	AverageRating   float64
	Author          string
	ThumbnailURL    string
	IsAgeRestricted bool
	IsUnlisted      bool
}

VideoInfo carries information of a video.

type VideoStream

type VideoStream struct {
	FileSize       int64     `json:"file_size"`
	MimeType       string    `json:"mime_type"`
	VideoCodec     string    `json:"video_codec"`
	AudioCodec     string    `json:"audio_codec"`
	Bitrate        int64     `json:"bitrate"`
	AverageBitrate int64     `json:"average_bitrate"`
	QualityLabel   string    `json:"quality_label"`
	Width          int       `json:"width"`
	Height         int       `json:"height"`
	HasAudio       bool      `json:"has_audio"`
	Expiration     time.Time `json:"expiration"`
	// contains filtered or unexported fields
}

VideoStream represents a stream of type 'video'.

func (*VideoStream) Download

func (stream *VideoStream) Download(destdir, filename string, overwrite bool, onStart func(total int64), onProgress func(written int64)) (path string, err error)

Download downloads the content of this stream and saves it to a file in the local machine. If `destdir` is empty, it defaults to the current directory. If `filename` is empty, it defaults to the name of this stream (i.e. `Name()`). If `overwrite` is true, it will overwrite the existing file of the same filename, skip downloading otherwise. `onProgress` is called whenever `Write()` occurrs, with the total amount of written bytes provided as parameter.

func (*VideoStream) GetDownloadURL

func (stream *VideoStream) GetDownloadURL() (string, error)

GetDownloadURL gets the decrypted URL to the direct source of this stream that can be used for downloading.

func (*VideoStream) Itag

func (stream *VideoStream) Itag() int

Itag returns the itag of this stream.

func (*VideoStream) Metadata

func (stream *VideoStream) Metadata() map[string]interface{}

Metadata returns a map consisting all the fields of this stream.

func (*VideoStream) Name

func (stream *VideoStream) Name() string

Name returns the name of this stream.

func (*VideoStream) ParentVideo

func (stream *VideoStream) ParentVideo() *Video

ParentVideo returns a pointer to the video object that this stream belongs to.

func (*VideoStream) Subtype

func (stream *VideoStream) Subtype() string

Subtype returns the subtype (extension) gotten from mime type of this stream.

func (*VideoStream) Type

func (stream *VideoStream) Type() string

Type returns the type of this stream. (video or video+audio)

type VideoStreams

type VideoStreams []*VideoStream

VideoStreams represents a sequence of streams of type 'video' (can be with / without audio).

func (VideoStreams) Best

func (streams VideoStreams) Best() *VideoStream

Best returns the `VideoStream` object with the highest resolution.

func (VideoStreams) First

func (streams VideoStreams) First() *VideoStream

First returns the first `VideoStream` object in this `VideoStreams`.

func (VideoStreams) Last

func (streams VideoStreams) Last() *VideoStream

Last returns the last `VideoStream` object in this `VideoStreams`.

func (VideoStreams) WithAudio

func (streams VideoStreams) WithAudio() (videoStreams VideoStreams)

WithAudio returns a copy of `VideoStreams` containing only `VideoStream` objects that also has audio.

func (VideoStreams) Worst

func (streams VideoStreams) Worst() *VideoStream

Worst returns the `VideoStream` object with the lowest resolution.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL