crunchyroll

package module
v2.2.2 Latest Latest
Warning

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

Go to latest
Published: May 18, 2022 License: LGPL-3.0 Imports: 20 Imported by: 0

README

Version 2 is out 🥳, see all the changes.

crunchyroll-go

A Go library & cli for the undocumented crunchyroll api. To use it, you need a crunchyroll premium account to for full (api) access.

Code size Download Badge License Go version Release Discord CI

CLI 🖥️Library 📚Disclaimer ☝️License ⚖

🖥️ CLI

✨ Features

  • Download single videos and entire series from crunchyroll.
  • Archive episode or seasons in an .mkv file with multiple subtitles and audios and compress them to gzip or zip files.
  • Specify a range which episodes to download from an anime.

💾 Get the executable

  • 📥 Download the latest binaries here or get it from below:
  • If you use Arch btw. or any other Linux distro which is based on Arch Linux, you can download the package via the AUR:
    $ yay -S crunchyroll-go
    
  • On Windows scoop can be used to install it (added by @AdmnJ):
    $ scoop bucket add extras # <- in case you haven't added the extra repository already
    $ scoop install crunchyroll-go
    
  • 🛠 Build it yourself. Must be done if your target platform is not covered by the provided binaries (like Raspberry Pi or M1 Mac):
    • use make (requires go to be installed):
    $ git clone https://github.com/ByteDream/crunchyroll-go
    $ cd crunchyroll-go
    $ make
    $ sudo make install # <- only if you want to install it on your system
    
    • use go:
    $ git clone https://github.com/ByteDream/crunchyroll-go
    $ cd crunchyroll-go
    $ go build -o crunchy cmd/crunchyroll-go/main.go
    

📝 Examples

Before reading: Because of the huge functionality not all cases can be covered in the README. Make sure to check the wiki, further usages and options are described there.

Login

Before you can do something, you have to log in first.

This can be performed via crunchyroll account email and password.

$ crunchy login user@example.com password

or via session id

$ crunchy login --session-id 8e9gs135defhga790dvrf2i0eris8gts
Download

By default, the cli tries to download the episode with your system language as audio. If no streams with your system language are available, the video will be downloaded with japanese audio and hardsubbed subtitles in your system language. If your system language is not supported, an error message will be displayed and en-US (american english) will be chosen as language.

$ crunchy download https://beta.crunchyroll.com/watch/GRDKJZ81Y/alone-and-lonesome

With -r best the video(s) will have the best available resolution (mostly 1920x1080 / Full HD).

$ crunchy download -r best https://beta.crunchyroll.com/watch/GRDKJZ81Y/alone-and-lonesome

The file is by default saved as a .ts (mpeg transport stream) file. .ts files may can't be played or are looking very weird (it depends on the video player you are using). With the -o flag, you can change the name (and file ending) of the output file. So if you want to save it as, for example, mp4 file, just name it whatever.mp4. You need ffmpeg to store the video in other file formats.

$ crunchy download -o "daaaaaaaaaaaaaaaarling.ts" https://beta.crunchyroll.com/watch/GRDKJZ81Y/alone-and-lonesome

With the --audio flag you can specify which audio the video should have and with --subtitle which subtitle it should have. Type crunchy help download to see all available locales.

$ crunchy download --audio ja-JP --subtitle de-DE https://beta.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx
Flags

The following flags can be (optional) passed to modify the download process.

Short Extended Description
-a --audio Forces audio of the video(s).
-s --subtitle Forces subtitle of the video(s).
-d --directory Directory to download the video(s) to.
-o --output Name of the output file.
-r --resolution The resolution of the video(s). best for best resolution, worst for worst.
-g --goroutines Sets how many parallel segment downloads should be used.
Archive

Archive works just like download. It downloads the given videos as .mkv files and stores all (soft) subtitles in it. Default audio locales are japanese and your system language (if available) but you can set more or less with the --language flag.

Archive a file

$ crunchy archive https://beta.crunchyroll.com/watch/GRDKJZ81Y/alone-and-lonesome

Downloads the first two episode of Darling in the FranXX and stores it compressed in a file.

$ crunchy archive -c "ditf.tar.gz" https://beta.crunchyroll.com/series/GY8VEQ95Y/darling-in-the-franxx
Flags

The following flags can be (optional) passed to modify the archive process.

Short Extended Description
-l --language Audio locale which should be downloaded. Can be used multiple times.
-d --directory Directory to download the video(s) to.
-o --output Name of the output file.
-m --merge Sets the behavior of the stream merging. Valid behaviors are 'auto', 'audio', 'video'. See the wiki for more information.
-c --compress If is set, all output will be compresses into an archive. This flag sets the name of the compressed output file and the file ending specifies the compression algorithm (gzip, tar, zip are supported).
-r --resolution The resolution of the video(s). best for best resolution, worst for worst.
-g --goroutines Sets how many parallel segment downloads should be used.
Help
  • General help

    $ crunchy help
    
  • Login help

    $ crunchy help login
    
  • Download help

    $ crunchy help download
    
  • Archive help

    $ crunchy help archive
    
Global flags

These flags you can use across every sub-command:

Flag Description
-q Disables all output.
-v Shows additional debug output.
-p Use a proxy to hide your ip / redirect your traffic.

📚 Library

Download the library via go get

$ go get github.com/ByteDream/crunchyroll-go/v2

The documentation is available on pkg.go.dev.

Examples how to use the library and some features of it are described in the wiki.

☝️ Disclaimer

This tool is ONLY meant to be used for private purposes. To use this tool you need crunchyroll premium anyway, so there is no reason why rip and share the episodes.

The responsibility for what happens to the downloaded videos lies entirely with the user who downloaded them.

⚖ License

This project is licensed under the GNU Lesser General Public License v3.0 (LGPL-3.0) - see the LICENSE file for more details.

Documentation

Index

Constants

View Source
const (
	JP LOCALE = "ja-JP"
	US        = "en-US"
	LA        = "es-419"
	ES        = "es-ES"
	FR        = "fr-FR"
	PT        = "pt-PT"
	BR        = "pt-BR"
	IT        = "it-IT"
	DE        = "de-DE"
	RU        = "ru-RU"
	AR        = "ar-SA"
)

Variables

This section is empty.

Functions

func ParseBetaEpisodeURL

func ParseBetaEpisodeURL(url string) (episodeId string, ok bool)

ParseBetaEpisodeURL tries to extract the episode id of the given crunchyroll beta url, pointing to an episode.

func ParseBetaSeriesURL

func ParseBetaSeriesURL(url string) (seasonId string, ok bool)

ParseBetaSeriesURL tries to extract the season id of the given crunchyroll beta url, pointing to a season.

func ParseEpisodeURL deprecated

func ParseEpisodeURL(url string) (seriesName, title string, episodeNumber int, webId int, ok bool)

ParseEpisodeURL tries to extract the crunchyroll series name, title, episode number and web id out of the given crunchyroll url Note that the episode number can be misleading. For example if an episode has the episode number 23.5 (slime isekai) the episode number will be 235.

Deprecated: Crunchyroll classic urls are sometimes not safe to use, use ParseBetaEpisodeURL if possible since beta url are always safe to use. The method will stay in the library until only beta urls are supported by crunchyroll itself.

func ParseVideoURL deprecated

func ParseVideoURL(url string) (seriesName string, ok bool)

ParseVideoURL tries to extract the crunchyroll series / movie name out of the given url.

Deprecated: Crunchyroll classic urls are sometimes not safe to use, use ParseBetaSeriesURL if possible since beta url are always safe to use. The method will stay in the library until only beta urls are supported by crunchyroll itself.

Types

type Crunchyroll

type Crunchyroll struct {
	// Client is the http.Client to perform all requests over.
	Client *http.Client
	// Context can be used to stop requests with Client and is context.Background by default.
	Context context.Context
	// Locale specifies in which language all results should be returned / requested.
	Locale LOCALE
	// SessionID is the crunchyroll session id which was used for authentication.
	SessionID string

	// Config stores parameters which are needed by some api calls.
	Config struct {
		TokenType   string
		AccessToken string

		CountryCode    string
		Premium        bool
		Channel        string
		Policy         string
		Signature      string
		KeyPairID      string
		AccountID      string
		ExternalID     string
		MaturityRating string
	}
	// contains filtered or unexported fields
}

func LoginWithCredentials

func LoginWithCredentials(user string, password string, locale LOCALE, client *http.Client) (*Crunchyroll, error)

LoginWithCredentials logs in via crunchyroll username or email and password.

func LoginWithSessionID

func LoginWithSessionID(sessionID string, locale LOCALE, client *http.Client) (*Crunchyroll, error)

LoginWithSessionID logs in via a crunchyroll session id. Session ids are automatically generated as a cookie when visiting https://www.crunchyroll.com.

func (*Crunchyroll) ExtractEpisodesFromUrl

func (c *Crunchyroll) ExtractEpisodesFromUrl(url string, audio ...LOCALE) ([]*Episode, error)

ExtractEpisodesFromUrl extracts all episodes from an url. If audio is not empty, the episodes gets filtered after the given locale.

func (*Crunchyroll) FindEpisodeByName

func (c *Crunchyroll) FindEpisodeByName(seriesName, episodeTitle string) ([]*Episode, error)

FindEpisodeByName finds an episode by its crunchyroll series name and episode title. Use this in combination with ParseEpisodeURL and hand over the corresponding results to this function.

func (*Crunchyroll) FindVideoByName deprecated

func (c *Crunchyroll) FindVideoByName(seriesName string) (Video, error)

FindVideoByName finds a Video (Season or Movie) by its name. Use this in combination with ParseVideoURL and hand over the corresponding results to this function.

Deprecated: Use Search instead. The first result sometimes isn't the correct one so this function is inaccurate in some cases. See https://github.com/ByteDream/crunchyroll-go/issues/22 for more information.

func (*Crunchyroll) IsCaching

func (c *Crunchyroll) IsCaching() bool

IsCaching returns if data gets cached or not. See SetCaching for more information.

func (*Crunchyroll) ParseUrl

func (c *Crunchyroll) ParseUrl(url string) (*Series, []*Episode, error)

ParseUrl parses the given url into a series or episode. The returning episode is a slice because non-beta urls have the same episode with different languages.

func (*Crunchyroll) Search

func (c *Crunchyroll) Search(query string, limit uint) (s []*Series, m []*Movie, err error)

Search searches a query and returns all found series and movies within the given limit.

func (*Crunchyroll) SetCaching

func (c *Crunchyroll) SetCaching(caching bool)

SetCaching enables or disables internal caching of requests made. Caching is enabled by default. If it is disabled the already cached data still gets called. The best way to prevent this is to create a complete new Crunchyroll struct.

type Downloader

type Downloader struct {
	// The output is all written to Writer.
	Writer io.Writer

	// TempDir is the directory where the temporary segment files should be stored.
	// The files will be placed directly into the root of the directory.
	// If empty a random temporary directory on the system's default tempdir
	// will be created.
	// If the directory does not exist, it will be created.
	TempDir string
	// If DeleteTempAfter is true, the temp directory gets deleted afterwards.
	// Note that in case of a hard signal exit (os.Interrupt, ...) the directory
	// will NOT be deleted. In such situations try to catch the signal and
	// cancel Context.
	DeleteTempAfter bool

	// Context to control the download process with.
	// There is a tiny delay when canceling the context and the actual stop of the
	// process. So it is not recommend stopping the program immediately after calling
	// the cancel function. It's better when canceling it and then exit the program
	// when Format.Download throws an error. See the signal handling section in
	// cmd/crunchyroll-go/cmd/download.go for an example.
	Context context.Context

	// Goroutines is the number of goroutines to download segments with.
	Goroutines int

	// A method to call when a segment was downloaded.
	// Note that the segments are downloaded asynchronously (depending on the count of
	// Goroutines) and the function gets called asynchronously too, so for example it is
	// first called on segment 1, then segment 254, then segment 3 and so on.
	OnSegmentDownload func(segment *m3u8.MediaSegment, current, total int, file *os.File) error
	// If LockOnSegmentDownload is true, only one OnSegmentDownload function can be called at
	// once. Normally (because of the use of goroutines while downloading) multiple could get
	// called simultaneously.
	LockOnSegmentDownload bool

	// If FFmpegOpts is not nil, ffmpeg will be used to merge and convert files.
	// The given opts will be used as ffmpeg parameters while merging.
	//
	// If Writer is *os.File and -f (which sets the output format) is not specified, the output
	// format will be retrieved by its file ending. If this is not the case and -f is not given,
	// the output format will be mpegts / mpeg transport stream.
	// Execute 'ffmpeg -muxers' to see all available output formats.
	FFmpegOpts []string
}

Downloader is used to download Format's

func NewDownloader

func NewDownloader(context context.Context, writer io.Writer, goroutines int, onSegmentDownload func(segment *m3u8.MediaSegment, current, total int, file *os.File) error) Downloader

NewDownloader creates a downloader with default settings which should fit the most needs.

type Episode

type Episode struct {
	ID        string `json:"id"`
	ChannelID string `json:"channel_id"`

	SeriesID        string `json:"series_id"`
	SeriesTitle     string `json:"series_title"`
	SeriesSlugTitle string `json:"series_slug_title"`

	SeasonID        string `json:"season_id"`
	SeasonTitle     string `json:"season_title"`
	SeasonSlugTitle string `json:"season_slug_title"`
	SeasonNumber    int    `json:"season_number"`

	Episode             string  `json:"episode"`
	EpisodeNumber       int     `json:"episode_number"`
	SequenceNumber      float64 `json:"sequence_number"`
	ProductionEpisodeID string  `json:"production_episode_id"`

	Title            string `json:"title"`
	SlugTitle        string `json:"slug_title"`
	Description      string `json:"description"`
	NextEpisodeID    string `json:"next_episode_id"`
	NextEpisodeTitle string `json:"next_episode_title"`

	HDFlag        bool `json:"hd_flag"`
	IsMature      bool `json:"is_mature"`
	MatureBlocked bool `json:"mature_blocked"`

	EpisodeAirDate time.Time `json:"episode_air_date"`

	IsSubbed       bool     `json:"is_subbed"`
	IsDubbed       bool     `json:"is_dubbed"`
	IsClip         bool     `json:"is_clip"`
	SeoTitle       string   `json:"seo_title"`
	SeoDescription string   `json:"seo_description"`
	SeasonTags     []string `json:"season_tags"`

	AvailableOffline bool   `json:"available_offline"`
	Slug             string `json:"slug"`

	Images struct {
		Thumbnail [][]struct {
			Width  int    `json:"width"`
			Height int    `json:"height"`
			Type   string `json:"type"`
			Source string `json:"source"`
		} `json:"thumbnail"`
	} `json:"images"`

	DurationMS    int    `json:"duration_ms"`
	IsPremiumOnly bool   `json:"is_premium_only"`
	ListingID     string `json:"listing_id"`

	SubtitleLocales []LOCALE `json:"subtitle_locales"`
	Playback        string   `json:"playback"`

	AvailabilityNotes string `json:"availability_notes"`

	StreamID string
	// contains filtered or unexported fields
}

Episode contains all information about an episode.

func EpisodeFromID

func EpisodeFromID(crunchy *Crunchyroll, id string) (*Episode, error)

EpisodeFromID returns an episode by its api id.

func (*Episode) AudioLocale

func (e *Episode) AudioLocale() (LOCALE, error)

AudioLocale returns the audio locale of the episode. Every episode in a season (should) have the same audio locale, so if you want to get the audio locale of a season, just call this method on the first episode of the season.

func (*Episode) GetFormat

func (e *Episode) GetFormat(resolution string, subtitle LOCALE, hardsub bool) (*Format, error)

GetFormat returns the format which matches the given resolution and subtitle locale.

func (*Episode) Streams

func (e *Episode) Streams() ([]*Stream, error)

Streams returns all streams which are available for the episode.

type Format

type Format struct {
	ID string
	// FormatType represents if the format parent is an episode or a movie.
	FormatType  FormatType
	Video       *m3u8.Variant
	AudioLocale LOCALE
	Hardsub     LOCALE
	Subtitles   []*Subtitle
	// contains filtered or unexported fields
}

Format contains detailed information about an episode video stream.

func (*Format) Download

func (f *Format) Download(downloader Downloader) error

Download downloads the Format with the via Downloader specified options.

func (*Format) InitVideo

func (f *Format) InitVideo() error

InitVideo initializes the Format.Video completely. The Format.Video.Chunklist pointer is, by default, nil because an additional request must be made to receive its content. The request is not made when initializing a Format struct because it would probably cause an intense overhead since Format.Video.Chunklist is only used sometimes.

type FormatType

type FormatType string
const (
	EPISODE FormatType = "episodes"
	MOVIE              = "movies"
)

type LOCALE

type LOCALE string

LOCALE represents a locale / language.

type Movie

type Movie struct {
	Video

	// not generated when calling MovieFromID.
	MovieListingMetadata struct {
		AvailabilityNotes   string   `json:"availability_notes"`
		AvailableOffline    bool     `json:"available_offline"`
		DurationMS          int      `json:"duration_ms"`
		ExtendedDescription string   `json:"extended_description"`
		FirstMovieID        string   `json:"first_movie_id"`
		IsDubbed            bool     `json:"is_dubbed"`
		IsMature            bool     `json:"is_mature"`
		IsPremiumOnly       bool     `json:"is_premium_only"`
		IsSubbed            bool     `json:"is_subbed"`
		MatureRatings       []string `json:"mature_ratings"`
		MovieReleaseYear    int      `json:"movie_release_year"`
		SubtitleLocales     []LOCALE `json:"subtitle_locales"`
	} `json:"movie_listing_metadata"`

	Playback string `json:"playback"`

	PromoDescription string `json:"promo_description"`
	PromoTitle       string `json:"promo_title"`
	SearchMetadata   struct {
		Score float64 `json:"score"`
	}
	// contains filtered or unexported fields
}

Movie contains information about a movie.

func MovieFromID

func MovieFromID(crunchy *Crunchyroll, id string) (*Movie, error)

MovieFromID returns a movie by its api id.

func (*Movie) MovieListing

func (m *Movie) MovieListing() (movieListings []*MovieListing, err error)

MovieListing returns all videos corresponding with the movie.

type MovieListing

type MovieListing struct {
	ID string `json:"id"`

	Title       string `json:"title"`
	Slug        string `json:"slug"`
	SlugTitle   string `json:"slug_title"`
	Description string `json:"description"`

	Images struct {
		Thumbnail [][]struct {
			Width  int    `json:"width"`
			Height int    `json:"height"`
			Type   string `json:"type"`
			Source string `json:"source"`
		} `json:"thumbnail"`
	} `json:"images"`

	DurationMS       int    `json:"duration_ms"`
	IsPremiumOnly    bool   `json:"is_premium_only"`
	ListeningID      string `json:"listening_id"`
	IsMature         bool   `json:"is_mature"`
	AvailableOffline bool   `json:"available_offline"`
	IsSubbed         bool   `json:"is_subbed"`
	IsDubbed         bool   `json:"is_dubbed"`

	Playback          string `json:"playback"`
	AvailabilityNotes string `json:"availability_notes"`
	// contains filtered or unexported fields
}

MovieListing contains information about something which is called movie listing. I don't know what this means thb.

func MovieListingFromID

func MovieListingFromID(crunchy *Crunchyroll, id string) (*MovieListing, error)

MovieListingFromID returns a movie listing by its api id.

func (*MovieListing) AudioLocale

func (ml *MovieListing) AudioLocale() (LOCALE, error)

AudioLocale is same as Episode.AudioLocale.

func (*MovieListing) Streams

func (ml *MovieListing) Streams() ([]*Stream, error)

Streams returns all streams which are available for the movie listing.

type Season

type Season struct {
	ID        string `json:"id"`
	ChannelID string `json:"channel_id"`

	Title     string `json:"title"`
	SlugTitle string `json:"slug_title"`

	SeriesID     string `json:"series_id"`
	SeasonNumber int    `json:"season_number"`

	IsComplete bool `json:"is_complete"`

	Description   string   `json:"description"`
	Keywords      []string `json:"keywords"`
	SeasonTags    []string `json:"season_tags"`
	IsMature      bool     `json:"is_mature"`
	MatureBlocked bool     `json:"mature_blocked"`
	IsSubbed      bool     `json:"is_subbed"`
	IsDubbed      bool     `json:"is_dubbed"`
	IsSimulcast   bool     `json:"is_simulcast"`

	SeoTitle       string `json:"seo_title"`
	SeoDescription string `json:"seo_description"`

	AvailabilityNotes string `json:"availability_notes"`

	// the locales are always empty, idk why this may change in the future
	AudioLocales    []LOCALE
	SubtitleLocales []LOCALE
	// contains filtered or unexported fields
}

Season contains information about an anime season.

func SeasonFromID

func SeasonFromID(crunchy *Crunchyroll, id string) (*Season, error)

SeasonFromID returns a season by its api id.

func (*Season) AudioLocale

func (s *Season) AudioLocale() (LOCALE, error)

AudioLocale returns the audio locale of the season.

func (*Season) Episodes

func (s *Season) Episodes() (episodes []*Episode, err error)

Episodes returns all episodes which are available for the season.

type Series

type Series struct {
	Video

	PromoDescription string `json:"promo_description"`
	PromoTitle       string `json:"promo_title"`

	AvailabilityNotes   string   `json:"availability_notes"`
	EpisodeCount        int      `json:"episode_count"`
	ExtendedDescription string   `json:"extended_description"`
	IsDubbed            bool     `json:"is_dubbed"`
	IsMature            bool     `json:"is_mature"`
	IsSimulcast         bool     `json:"is_simulcast"`
	IsSubbed            bool     `json:"is_subbed"`
	MatureBlocked       bool     `json:"mature_blocked"`
	MatureRatings       []string `json:"mature_ratings"`
	SeasonCount         int      `json:"season_count"`

	// not generated when calling SeriesFromID.
	SearchMetadata struct {
		Score float64 `json:"score"`
	}
	// contains filtered or unexported fields
}

Series contains information about an anime series.

func SeriesFromID

func SeriesFromID(crunchy *Crunchyroll, id string) (*Series, error)

SeriesFromID returns a series by its api id.

func (*Series) Seasons

func (s *Series) Seasons() (seasons []*Season, err error)

Seasons returns all seasons of a series.

type Stream

type Stream struct {
	HardsubLocale LOCALE
	AudioLocale   LOCALE
	Subtitles     []*Subtitle
	// contains filtered or unexported fields
}

Stream contains information about all available video stream of an episode.

func StreamsFromID

func StreamsFromID(crunchy *Crunchyroll, id string) ([]*Stream, error)

StreamsFromID returns a stream by its api id.

func (*Stream) Formats

func (s *Stream) Formats() ([]*Format, error)

Formats returns all formats which are available for the stream.

type Subtitle

type Subtitle struct {
	Locale LOCALE `json:"locale"`
	URL    string `json:"url"`
	Format string `json:"format"`
	// contains filtered or unexported fields
}

Subtitle contains the information about a video subtitle.

func (Subtitle) Save

func (s Subtitle) Save(writer io.Writer) error

Save writes the subtitle to the given io.Writer.

type Video

type Video interface{}

Video is the base for Movie and Season.

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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