Documentation ¶
Overview ¶
Package govidious implements a wrapper over the Invidious REST API v1, which is described in these documents:
- https://github.com/iv-org/documentation/blob/master/docs/api.md
- https://github.com/iv-org/documentation/blob/master/docs/api/common_types.md
- https://github.com/iv-org/documentation/blob/master/docs/api/channels_endpoint.md
- https://github.com/iv-org/documentation/blob/master/docs/api/authenticated-endpoints.md
For each of the endpoints listed in those links, this module provides an API function which:
Takes as many input arguments as needed depending on the endpoint. For example, the "/api/v1/stat" endpoint is represented by the "Stat()" API function which takes no arguments, while the "/api/v1/search" endpoint is represented by the "Search()" API function which takes many arguments (search query, date, duration, ...).
Returns a structure that matches the JSON response associated to each endpoint.
In order to use this package first create a new "InvidiousV1" instance using the "New()" function:
import "git.sr.ht/~greenfoo/govidious" g := govidious.New("invidious.myserver.com", nil)
...then, simply call, on that object, the desired API function(s):
g.Search(...) g.Top(...) g.Videos(...)
For example, to get the URL of the most watched video featuring "kittens playing golf", you would do this:
response, _ := g.Search("kittens playing golf", 0, "view_count", "", "", "video", "", "") videoId := response.Videos[0].VideoId youtubeUrl := "https://www.youtube.com/watch?v="+videoId invidiousUrl := INVIDIOUS_SERVER + "/watch?v="+videoId
Notice that both URLs ("youtubeUrl" and "invidiousUrl") can be used on a web browser to actually watch the video. The main difference is that:
Using "youtubeUrl" establishes a direct connection with YouTube servers.
Using "invidiousUrl" might or might not establish a direct connection with YouTube servers, depending on how the Invidious server is configured. If you don't want to leave any trace of YouTube servers, make sure you use "InvidiousUrl" on an Invidious server configured to proxy video files.
Another thing you can do with this URL ("youtubeUrl" or "invidiousUrl") is to use the "mpv" player to start watching the video directly, without needing a web browser. Under the hood, "mpv" uses "youtube-dl" (another program) to parse the web page, find the URL of the video file (which might change depending on the options you call "mpv" with, such as the desired quality) and download it.
Well... the good news is that you don't need "mpv" nor "youtube-dl" to do all of this as the Invidious API can also be used to find out the URL of the video file once you have the "videoId".
First, you obtain all the associated data of the desired video:
response, _ = g.Videos(videoId, "")
...then you inspect the returned structure to find the URL of the video with the desired quality level:
for _, x := range response.AdaptiveFormats { if x.Resolution == ... { return x.Url } } for _, x := range response.FormatStreams { if x.Resolution == ... { return x.Url } }
There are many other things you can do with this package, such as listing all the videos from a given channel, retrieving the subtitles associated to a video, etc... Check the documentation of each function (and the name of the fields of the structures they return) for more details.
Example (Basic) ¶
package main import ( "fmt" "git.sr.ht/~greenfoo/govidious" ) const INVIDIOUS_SERVER = "https://invidious.snopyta.org" func main() { // This is how you print the title of all Rick Asley videos: g := govidious.New(INVIDIOUS_SERVER, nil) queryResults, _ := g.Search("Rick Asley", 0, "view_count", "", "", "video", "", "") for _, videoEntry := range queryResults.Videos { fmt.Println(videoEntry.Title) } }
Output:
Index ¶
- Variables
- type AnnotationsResponse
- type CaptionsResponse
- type ChannelsCommentsResponse
- type ChannelsLatestResponse
- type ChannelsPlaylistsResponse
- type ChannelsResponse
- type ChannelsSearchResponse
- type ChannelsVideosResponse
- type CommentsResponse
- type InsightsResponse
- type InvidiousV1
- func (i *InvidiousV1) Annotations(videoId string, source string) (AnnotationsResponse, error)
- func (i *InvidiousV1) CaptionByLabel(videoId, region, label string) (string, error)
- func (i *InvidiousV1) CaptionByLanguageCode(videoId, region, lang string, translationAllowed bool) (string, error)
- func (i *InvidiousV1) Captions(videoId, region string) (CaptionsResponse, error)
- func (i *InvidiousV1) Channels(authorId string) (ChannelsResponse, error)
- func (i *InvidiousV1) ChannelsComments(authorId, continuation string) (ChannelsCommentsResponse, error)
- func (i *InvidiousV1) ChannelsLatest(authorId string) (ChannelsLatestResponse, error)
- func (i *InvidiousV1) ChannelsPlaylists(authorId string, sortBy, continuation string) (ChannelsPlaylistsResponse, error)
- func (i *InvidiousV1) ChannelsSearch(videoId string) (ChannelsSearchResponse, error)
- func (i *InvidiousV1) ChannelsVideos(authorId string, sortBy string) (ChannelsVideosResponse, error)
- func (i *InvidiousV1) Comments(videoId, sortBy, source, continuation string) (CommentsResponse, error)
- func (i *InvidiousV1) IdToUrl(videoId string) (string, error)
- func (i *InvidiousV1) Insights(videoId string) (InsightsResponse, error)
- func (i *InvidiousV1) Mixes(videoId string) (MixesResponse, error)
- func (i *InvidiousV1) Playlists(playlistId string) (PlaylistsResponse, error)
- func (i *InvidiousV1) Popular() (PopularResponse, error)
- func (i *InvidiousV1) Search(query string, page int32, ...) (SearchResponse, error)
- func (i *InvidiousV1) SearchSuggestions(videoId string) (SearchSuggestionsResponse, error)
- func (i *InvidiousV1) Stats() (StatsResponse, error)
- func (i *InvidiousV1) Top() (TopResponse, error)
- func (i *InvidiousV1) Trending(category, region string) (TrendingResponse, error)
- func (i *InvidiousV1) Videos(videoId, region string) (VideosResponse, error)
- type MixesResponse
- type PlaylistsResponse
- type PopularResponse
- type SearchResponse
- type SearchResponseTypeChannel
- type SearchResponseTypePlaylist
- type SearchResponseTypeVideo
- type SearchSuggestionsResponse
- type StatsResponse
- type TopResponse
- type TrendingResponse
- type VideosResponse
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( ErrInvidiousClientError = errors.New("HTTP client returned an error") ErrInvidiousServerError = errors.New("HTTP server returned an error") ErrInvidiousServerInvalidResponse = errors.New("HTTP server returned invalid data") )
Errors that this API might return
Functions ¶
This section is empty.
Types ¶
type AnnotationsResponse ¶
type AnnotationsResponse struct {
XmlData string
}
AnnotationsResponse is the structure returned when calling "Annotations()". Notice how this structure is different from the rest in that it contains a big blob of XML data (instead of a more structured tree of fields) that you will need to parse yourself.
type CaptionsResponse ¶
type CaptionsResponse struct { Captions []struct { Label string `json:"label"` LanguageCode string `json:"languageCode"` Url string `json:"url"` } `json:"captions"` }
CaptionsResponse is the structure returned when calling "Captions()"
type ChannelsCommentsResponse ¶
type ChannelsCommentsResponse struct { AuthorId string `json:"authorId"` Comments []struct { Author string `json:"author"` AuthorThumbnails []struct { Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"authorThumbnails"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` IsEdited bool `json:"isEdited"` Content string `json:"content"` ContentHtml string `json:"contentHtml"` Published int64 `json:"published"` PublishedText string `json:"publishedText"` LikeCount int32 `json:"likeCount"` CommentId string `json:"commentId"` AuthorIsChannelOwner bool `json:"authorIsChannelOwner"` CreatorHeart struct { CreatorThumbnail string `json:"creatorThumbnail"` CreatorName string `json:"CreatorName"` } `json:"creatorHeart"` Replies struct { ReplyCount int32 `json:"replyCount"` Continuation string `json:"Continuation"` } `json:"replies"` Attachment struct{} `json:"attachment"` } `json:"comments"` Continuation string `json:"Continuation"` }
ChannelsCommentsResponse is the structure returned when calling "ChannelsComments()"
TODO: Support for different types of attachements
type ChannelsLatestResponse ¶
type ChannelsLatestResponse ChannelsVideosResponse
ChannelsLatestResponse is the structure returned when calling "ChannelsLatest()"
type ChannelsPlaylistsResponse ¶
type ChannelsPlaylistsResponse struct { Playlists []struct { Title string `json:"title"` PlaylistId string `json:"playlistId"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` VideoCount int32 `json:"videoCount"` Videos []struct { Title string `json:"title"` VideoId string `json:"videoId"` LengthSeconds int32 `json:"lengthSeconds"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` } `json:"videos"` } `json:"playlists"` Continuation string `json:"continuation"` }
ChannelsPlaylistsResponse is the structure returned when calling "ChannelsPlaylists()"
type ChannelsResponse ¶
type ChannelsResponse struct { Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` AuthorThumbnails []struct { Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"authorThumbnails"` SubCount int32 `json:"subCount"` TotalViews int64 `json:"totalViews"` Joined int64 `json:"joined"` Paid bool `json:"paid"` AutoGenerated bool `json:"autoGenerated"` IsFamilyFriendly bool `json:"insFamilyFriendly"` Description string `json:"description"` DescriptionHtml string `json:"descriptionHtml"` AllowedRegions []string `json:"string"` LatestVideos []struct { Title string `json:"title"` VideoId string `json:"videoId"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` Description string `json:"description"` DescriptionHtml string `json:"descriptionHtml"` ViewCount int64 `json:"viewCount"` Published int64 `json:"published"` PublishedText string `json:"publishedText"` LengthSeconds int32 `json:"lengthSeconds"` Paid bool `json:"paid"` Premium bool `json:"premium"` } `json:"latestVideos"` RelatedChannels []struct { Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` AuthorThumbnails struct { Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"authorThumbnails"` } }
ChannelsResponse is the structure returned when calling "Channels()"
type ChannelsSearchResponse ¶
type ChannelsSearchResponse struct { Videos []SearchResponseTypeVideo Playlists []SearchResponseTypePlaylist Channels []SearchResponseTypeChannel }
ChannelsSearchResponse is the structure returned when calling "ChannelsSearch()"
Notice how this structure does *not* match the original JSON structure defined in the Inviduous REST API document.
The original JSON structure is a list of dictionaries of different types (some elements of the list represent a video, others a playlist and others a channel).
The SearchResponse structure, instead, is made up of three homogeneous lists, one for each type of entry.
type ChannelsVideosResponse ¶
type ChannelsVideosResponse struct { Videos []VideosResponse `json:"videos"` Continuation string `json:"continuation"` }
ChannelsVideosResponse is the structure returned when calling "ChannelsVideos()"
type CommentsResponse ¶
type CommentsResponse struct { CommentCount int32 `json:"commentCount"` VideoId string `json:"videoId"` Comments []struct { Author string `json:"author"` AuthorThumbnails []struct { Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"authorThumbnails"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` IsEdited bool `json:"isEdited"` Content string `json:"content"` ContentHtml string `json:"contentHtml"` Published int64 `json:"published"` PublishedText string `json:"publishedText"` LikeCount int32 `json:"likeCount"` CommentId string `json:"commentId"` AuthorIsChannelOwner bool `json:"authorIsChannelOwner"` CreatorHeart struct { CreatorThumbnail string `json:"creatorThumbnail"` CreatorName string `json:"CreatorName"` } `json:"creatorHeart"` Replies struct { ReplyCount int32 `json:"replyCount"` Continuation string `json:"Continuation"` } `json:"replies"` } `json:"comments"` Continuation string `json:"Continuation"` }
CommentsResponse is the structure returned when calling "Comments()"
type InsightsResponse ¶
type InsightsResponse struct { ViewCount int64 `json:"viewCount"` TimeWatchedText string `json:"timeWatchedText"` SubscriptionsDriven int32 `json:"subscriptionsDriven"` AvgViewDurationSeconds int32 `json:"avgViewDurationSeconds"` GraphData struct{} `json:"graphData"` }
InsightsResponse is the structure returned when calling "Insights()"
type InvidiousV1 ¶
type InvidiousV1 struct {
// contains filtered or unexported fields
}
InvidiousV1 is the structure returned when calling "New()". You later use it to call the rest of API functions
func New ¶
func New(serverUrl string, lg *log.Logger) *InvidiousV1
New creates an Invidious object, which is later used to call the rest of API functions. This is always the first function of this API you have to call.
The first argument ("serverUrl") is the URL of the Invidious server, which will typically be your own server. However, you can also use one of the many public instances, some of which are listed here: https://github.com/iv-org/documentation/blob/master/Invidious-Instances.md
Note that the server *must* be configured to expose the REST API (and *not* all the server from the previous list do that).
The second argument ("lg") is a "log" object that this module will use to print log messages. If you set this to "nil", log messages will not be printed.
Example #1 (no logging):
i := New("invidious.myservername.com", nil) i.Search(...) i.Videos(...)
Example #2 (logging to stderr):
i := New("invidious.myservername.com", log.New(os.Stderr, "GOVIDIOUS", log.Ltime | log.Lshortfile)) i.Search(...) i.Videos(...)
func (*InvidiousV1) Annotations ¶
func (i *InvidiousV1) Annotations(videoId string, source string) (AnnotationsResponse, error)
Annotations returns an XML blob with all the annotations the video contains ("annotations" are pieces of text intended to appear on top of the video in the form of a pop up to bring attention to something).
The first argument ("videoId") is the same one "Videos()" takes.
The second argument ("source") can be either "archive" or "youtube", and it tells where to retrieve the annotations from (either from "https://archive.org/details/youtubeannotations" or from YouTube itself). It looks like YouTube removed annotations some time ago (2018?): you can no longer create them and they have been removed from all past videos (!!). Fortunately, a copy was saved to "archive.org". In other words: you want to always use "archive" as the second argument to this function.
This function does not parse the returned XML blob. Fortunately it is not that hard to understand so you can do it yourself.
func (*InvidiousV1) CaptionByLabel ¶
func (i *InvidiousV1) CaptionByLabel(videoId, region, label string) (string, error)
CaptionByLabel returns the close captions of a video in webVTT format.
The first argument ("videoId") is the same one "Videos()" takes.
The second argument ("region") is the same one "Videos()" takes.
The third argument ("label") is a string describing the language of the close captions that you want to retrieve. In order to find out what the valid values for "label" are for a particular video, call first "Captions()", which returns an array where each entry is tagged with a particular "label" such as, for example, "Spanish".
The returned text contains all the captions in the requested language in webVTT format (see https://en.wikipedia.org/wiki/WebVTT)
func (*InvidiousV1) CaptionByLanguageCode ¶
func (i *InvidiousV1) CaptionByLanguageCode(videoId, region, lang string, translationAllowed bool) (string, error)
CaptionByLanguageCode returns the close captions of a video in webVTT format.
The first argument ("videoId") is the same one "Videos()" takes.
The second argument ("region") is the same one "Videos()" takes.
The third argument ("lang") is a two lowercase characters ISO 639-1 language code (you can check them here, on the column called "639-1": https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes). The returned text will be in that language (if available) or...
When the fourth argument ("translationAllowed") is set to "false", this function will fail when the video does not contain close captions in the requested language. In order to obtain the list of available languages for a particular video, call first "Captions()", which returns an array where each entry is tagged with a particualr "languageCode" such as, for example, "es" When set to "true", this function will ask the server to try to auto-generate a translation in the requested language before failing (which can still happen for whatever reason).
The returned text contains all the captions in the requested language in webVTT format (see https://en.wikipedia.org/wiki/WebVTT)
func (*InvidiousV1) Captions ¶
func (i *InvidiousV1) Captions(videoId, region string) (CaptionsResponse, error)
Captions returns the list of languages for which close captions for the specified video are available.
The first argument ("videoId") is the same one "Videos()" takes.
The second argument ("region") is the same one "Videos()" takes.
The returned "CaptionsResponse" structure will contain an array ("captions") -which might be empty- with one entry for each language-specific close caption available. From all the returned entries you are expected to select one, take note of either its "label" (ex: "Spanish") or its "languageCode" (ex: "es") and then call either "CaptionByLabel()" or "CaptionByLanguageCode()" to, finally, obtain the close captions.
For example:
r, err := g.Captions("Q8Sq9r50gc0", "US") ...(make sure "Spanish"/"es" is returned inside "r")... t, err := g.CaptionByLabel("Q8Sq9r50gc0", "US", "Spanish") ...or... t, err := g.CaptionByLanguageCode("Q8Sq9r50gc0", "US", "es", false)
func (*InvidiousV1) Channels ¶
func (i *InvidiousV1) Channels(authorId string) (ChannelsResponse, error)
Channels returns, despite of its name, information about *one* particular channel such as a text description, the author name, list of latest videos on the channel (*not* the list of *all* videos, for that you need to call "ChannelsVideos()"), ...
The first argument ("authorId") is a string used to identify the owner of the channel. It can be obtained from several other API calls such as "Search()", "Popular()", "Top()", ... Note that the "authorId" string obtained in the response to those other API functions looks like random (ex: "UCSMOQeBJ2RAnuFungnQOxLg" for the "Blender" channel). HOWEVER it looks like you can also use, instead, another human readable identifier (such as "BlenderFoundation") to obtain the same result. I haven't been able to find where to obtain this alternative human redable identifier, though... I'll update this comment once I do.
func (*InvidiousV1) ChannelsComments ¶
func (i *InvidiousV1) ChannelsComments(authorId, continuation string) (ChannelsCommentsResponse, error)
ChannelsComments returns the list of entries published by a channel author on the channel's "community" section.
The first argument ("authorId") is the same one "Channels()" takes.
The second argument ("continuation") is the same one "Comments()" takes.
func (*InvidiousV1) ChannelsLatest ¶
func (i *InvidiousV1) ChannelsLatest(authorId string) (ChannelsLatestResponse, error)
ChannelsLatest returns a list of the latest videos from a channel. The returned list is the same as the one you would get by calling "ChannelsVideos(..., 1, "newer")" except it contains less entries.
The first argument ("authorId") is the same one "Channels()" takes.
func (*InvidiousV1) ChannelsPlaylists ¶
func (i *InvidiousV1) ChannelsPlaylists(authorId string, sortBy, continuation string) (ChannelsPlaylistsResponse, error)
ChannelsPlaylists returns a list of the playlists associated to a channel.
The first argument ("authorId") is the same one "Channels()" takes.
The second argument ("sort_by") can be set to one of these: "newest" (meaning "first the playlist most recently created"), "oldest" (which means the opposite) or "last" (which means "first the playlist where a new video was most recenty added). You can also leave it empty (""), which means "last".
The third argument ("continuation") is the same one "Comments()" takes.
func (*InvidiousV1) ChannelsSearch ¶
func (i *InvidiousV1) ChannelsSearch(videoId string) (ChannelsSearchResponse, error)
func (*InvidiousV1) ChannelsVideos ¶
func (i *InvidiousV1) ChannelsVideos(authorId string, sortBy string) (ChannelsVideosResponse, error)
ChannelsVideos returns a list with all the videos from a channel.
The first argument ("authorId") is the same one "Channels()" takes.
The third argument ("sort_by") is the same one "Channels()" takes.
func (*InvidiousV1) Comments ¶
func (i *InvidiousV1) Comments(videoId, sortBy, source, continuation string) (CommentsResponse, error)
Comments returns all the comments associated to a video.
The first argument ("videoId") is the same one "Videos()" takes.
The second argument ("sortBy") can be either "top" or "new" to sort the comments by most voted of most recently posted respectively.
The third argument ("source") can be either "youtube" or "reddit" to obtain the comments from YoutTube itself or from "http://reddit.com/r/FellowKids" respectively.
TODO: When using "reddit", the returned json object from the Indivious server does not match the (expected) structure defined by the "CommentsResponse" type. Because of this, when setting "source" to "reddit", this functions returns an empty object. This is something that will be fixed in the future (maybe creating one function for each "source" or maybe making this function return one extra structure that will be the one filled in the "reddit" case).
The fourth argument ("continuation") is used to retrieve a given "page" of comments. This is how it works: The first time, call this functions with "continuation" set to an empty string and you will receive a "CommentsResponse" object with a "continuation" field. If you then want to retrive more comments from that same video, you need to call this function once again, with the same arguments, except for "continuation", which must now be set to that value obtained in the previous response... and so on until the returned object contains an empty "continuation" field.
func (*InvidiousV1) Insights ¶
func (i *InvidiousV1) Insights(videoId string) (InsightsResponse, error)
Insights returns analytics information about one particular video. Unfortunately YouTube has removed publicly-available analytics and this function will always return an error (ErrInvidiousServerInvalidResponse)
The first argument ("videoId") is the same one "Videos()" takes.
func (*InvidiousV1) Mixes ¶
func (i *InvidiousV1) Mixes(videoId string) (MixesResponse, error)
func (*InvidiousV1) Playlists ¶
func (i *InvidiousV1) Playlists(playlistId string) (PlaylistsResponse, error)
func (*InvidiousV1) Popular ¶
func (i *InvidiousV1) Popular() (PopularResponse, error)
Trending returns a list of "popular" videos.
It is not clear what the difference betwen "trending", "top" and "popular" videos is (that is up to YouTube to decide).
func (*InvidiousV1) Search ¶
func (i *InvidiousV1) Search(query string, page int32, sort_by, date, duration, category, features, region string) (SearchResponse, error)
Search returns a list of videos, playlists and/or channels that match the provided arguments.
In particular, the returned "SearchResponse" type contains three lists (one for videos, one for playlists and one for channels). Any (or even all) of them can be empty.
The first argument ("query") is the piece of text you want to search for (ex: "typing monkey")
The second argument ("page") is the page of results that you want to get. You typically want to start with "1" and keep increasing "2", "3", ... There doesn't seem to be a practical limit for this argument.
The third argument ("sort_by") can be set to one of these: "relevance", "rating", "upload_date" or "view_count". You can also leave it empty (""), which seems to have a similar effect to "relevance" (but results are not exactly the same!)
The fourth argument ("date") can be set to "hour", "today", "week", "month" or "year" to limit the returned results to only entries published in the last hour, today, last week, last month or last year respectively. You can also leave it empty (""), which means "I want results from all times".
The fifth argument ("duration") can be set to "short" or "long". You can also leave it empty (""), which means "any length". "Short" videos seem to be shorter than 5 minutes, while "long" videos seems to be longer than 20 minutes, but don't quote me on that :)
The sixth argument ("category") can be set to "video", "playlist", "channel" or "all". If you leave it empty ("") it has the same effect as "video". When you use something different from "all", the returned "SearchResponse" structure will contain two empty lists (ex: if you set "category" to "video", then the returned "playlist" and "channel" lists will be empty).
The seventh argument ("features") can be set to a comma separated list (no spaces) of one or more of the following elements: "hd", "subtitles", "creative_commons", "3d", "live", "purchased", "4k", "360", "location", "hdr". It can also be left empty (""), which means "no special features required".
The eighth argument ("region") is the same one "Videos()" takes.
func (*InvidiousV1) SearchSuggestions ¶
func (i *InvidiousV1) SearchSuggestions(videoId string) (SearchSuggestionsResponse, error)
func (*InvidiousV1) Stats ¶
func (i *InvidiousV1) Stats() (StatsResponse, error)
Stats returns information about the Invidious server you are connected to, such as the server version, number of users, etc...
func (*InvidiousV1) Top ¶
func (i *InvidiousV1) Top() (TopResponse, error)
Trending returns a list of "top" videos.
It is not clear what the difference betwen "trending", "top" and "popular" videos is (that is up to YouTube to decide).
*DEPRECATION WARNING*: The "top" feed was removed from Invidious implementation in late 2020, thus you will probably receive an error when calling this function. See [here](https://github.com/iv-org/invidious/pull/1592)
func (*InvidiousV1) Trending ¶
func (i *InvidiousV1) Trending(category, region string) (TrendingResponse, error)
Trending returns a list of currently "trending" videos.
It is not clear what the difference betwen "trending", "top" and "popular" videos is (that is up to YouTube to decide).
The first argument ("category") can be one of "music", "gaming", "news" or "movies". It can also be an empty string (""), which means you want the list of trending videos "overall" (without considering their category).
The second argument ("region") is the same one "Videos()" takes.
func (*InvidiousV1) Videos ¶
func (i *InvidiousV1) Videos(videoId, region string) (VideosResponse, error)
Videos returns, despite of its name, information about *one* particular video such as a text description, the author name, publication date, etc...
The first argument ("videoId") is a string used to identify one particular video from all those available in Invidious. It that can be obtained from several other API calls such as "Search()", "Popular()", "Top()", ...
The second argument ("region") is a two uppercase characters ISO 3166 country code (you can check them here, on the column called "Alpha-2 code": https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes). The contents of the response will be localized to the provided country code when available. If you leave this argument empty it will be set to "US".
type MixesResponse ¶
type MixesResponse struct { Title string `json:"title"` MixId string `json:"mixId"` Videos []struct { Title string `json:"title"` VideoId string `json:"videoId"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` Index string `json:"index"` LengthSeconds int32 `json:"lengthSeconds"` } `json:"videos"` }
MixesResponse is the structure returned when calling "Mixes()"
type PlaylistsResponse ¶
type PlaylistsResponse struct { Title string `json:"title"` PlaylistId string `json:"playlistId"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorThumbnails struct { Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"authorThumbnails"` Description string `json:"description"` DescriptionHtml string `json:"descriptionHtml"` VideoCount int32 `json:"videoCount"` ViewCount int64 `json:"viewCount"` Updated int64 `json:"updated"` Videos []struct { Title string `json:"title"` VideoId string `json:"videoId"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` Index string `json:"index"` LengthSeconds int32 `json:"lengthSeconds"` } `json:"videos"` }
PlaylistsResponse is the structure returned when calling "Playlists()"
type PopularResponse ¶
type PopularResponse []struct { Type string `json:"type"` Title string `json:"title"` VideoId string `json:"videoId"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` LengthSeconds int32 `json:"lengthSeconds"` ViewCount int64 `json:"viewCount"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` Published int64 `json:"published"` PublishedText string `json:"publishedText"` }
PopularResponse is the structure returned when calling "Popular()"
type SearchResponse ¶
type SearchResponse struct { Videos []SearchResponseTypeVideo Playlists []SearchResponseTypePlaylist Channels []SearchResponseTypeChannel }
SearchResponse is the structure returned when calling "Search()".
Notice how this structure does *not* match the original JSON structure defined in the Inviduous REST API document.
The original JSON structure is a list of dictionaries of different types (some elements of the list represent a video, others a playlist and others a channel).
The SearchResponse structure, instead, is made up of three homogeneous lists, one for each type of entry.
type SearchResponseTypeChannel ¶
type SearchResponseTypeChannel struct { Type string `json:"type"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` AuthorThumbnails []struct { Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } SubCount int32 `json:"subCount"` VideoCount int32 `json:"videoCount"` Description string `json:"description"` DescriptionHtml string `json:"descriptionHtml"` }
SearchResponseTypeChannel is a list containing playlist entries. It is embedded in the SearchResponse and ChannelsSearchResponse structures returned when calling "Search()" and "ChannelsSearch()" respectively.
type SearchResponseTypePlaylist ¶
type SearchResponseTypePlaylist struct { Type string `json:"type"` Title string `json:"title"` PlaylistId string `json:"playlistId"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` VideoCount int32 `json:"videoCount"` Videos []struct { Title string `json:"title"` VideoId string `json:"videoId"` LengthSeconds int32 `json:"lengthSeconds"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` } `json:"videos"` }
SearchResponseTypePlaylist is a list containing playlist entries. It is embedded in the SearchResponse and ChannelsSearchResponse structures returned when calling "Search()" and "ChannelsSearch()" respectively.
type SearchResponseTypeVideo ¶
type SearchResponseTypeVideo struct { Type string `json:"video"` Title string `json:"title"` VideoId string `json:"videoId"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` Description string `json:"description"` DescriptionHtml string `json:"descriptionHtml"` ViewCount int64 `json:"viewCount"` Published int64 `json:"published"` PublishedText string `json:"publishedText"` LengthSeconds int32 `json:"lengthSeconds"` LiveNow bool `json:"liveNow"` Paid bool `json:"paid"` Premium bool `json:"premium"` }
SearchResponseTypeVideo is a list containing video entries. It is embedded in the SearchResponse and ChannelsSearchResponse structures returned when calling "Search()" and "ChannelsSearch()" respectively.
type SearchSuggestionsResponse ¶
type SearchSuggestionsResponse struct { Query string `json:"query"` Suggestions []string `json:"suggestions"` }
SearchSuggestionsResponse is the structure returned when calling "SearchSuggestions()"
type StatsResponse ¶
type StatsResponse struct { Version string `json:"version"` Software struct { Name string `json:"name"` Version string `json:"version"` Branch string `json:"branch"` } `json:"software"` OpenRegistrations bool `json:"openRegistrations"` Usage struct { Users struct { Total int32 `json:"total"` ActiveHalfYear int32 `json:"activeHalfYear"` ActiveMonth int32 `json:"activeMonth"` } `json:"users"` } `json:"usage"` Metadata struct { UpdatedAt int64 `json:"updatedAt"` LastChannelRefreshedAt int64 `json:"lastChannelRefreshedAt"` } `json:"metadata"` }
StatsResponse is the structure returned when calling "Stats()"
type TopResponse ¶
type TopResponse []struct { Title string `json:"title"` VideoId string `json:"videoId"` VideoThumbnails struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` LengthSeconds int32 `json:"lengthSeconds"` ViewCount int64 `json:"viewCount"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` Published int64 `json:"published"` PublishedText string `json:"publishedText"` Description string `json:"description"` DescriptionHtml string `json:"descriptionHtml"` }
TopResponse is the structure returned when calling "Top()"
type TrendingResponse ¶
type TrendingResponse []struct { Title string `json:"title"` VideoId string `json:"videoId"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` LengthSeconds int32 `json:"lengthSeconds"` ViewCount int64 `json:"viewCount"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` Published int64 `json:"published"` PublishedText string `json:"publishedText"` Description string `json:"description"` DescriptionHtml string `json:"descriptionHtml"` LiveNow bool `json:"liveNow"` Paid bool `json:"paid"` Premium bool `json:"premium"` }
TrendingResponse is the structure returned when calling "Trending()"
type VideosResponse ¶
type VideosResponse struct { Title string `json:"title"` VideoId string `json:"videoId"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` Description string `json:"description"` DescriptionHtml string `json:"descriptionHtml"` Published int64 `json:"published"` PublishedText string `json:"publishedText"` Keywords []string `json:"keywords"` ViewCount int64 `json:"viewCount"` LikeCount int32 `json:"likeCount"` DislikeCount int32 `json:"dislikeCount"` Paid bool `json:"paid"` Premium bool `json:"premium"` IsFamilyFriendly bool `json:"isFamilyFriendly"` AllowedRegions []string `json:"allowedRegions"` Genre string `json:"genre"` GenreUrl string `json:"genreUrl"` Author string `json:"author"` AuthorId string `json:"authorId"` AuthorUrl string `json:"authorUrl"` AuthorThumbnails []struct { Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"authorThumbnails"` SubCountText string `json:"subCountText"` LengthSeconds int32 `json:"lengthSeconds"` AllowRatings bool `json:"allowRatings"` Rating float32 `json:"rating"` IsListed bool `json:"isListed"` LiveNow bool `json:"liveNow"` IsUpcoming bool `json:"isUpcoming"` PremiereTimestamp int64 `json:"premiereTimestamp"` HlsUrl string `json:"hlsUrl"` AdaptiveFormats []struct { Index string `json:"index"` Bitrate string `json:"bitrate"` Init string `json:"init"` Url string `json:"url"` Itag string `json:"itag"` Type string `json:"type"` Clen string `json:"clen"` Lmt string `json:"lmt"` ProjectionType string `json:"projectionType"` Container string `json:"container"` Encoding string `json:"encoding"` QualityLabel string `json:"qualityLabel"` Resolution string `json:"resolution"` } `json:"adaptiveFormats"` FormatStreams []struct { Url string `json:"url"` Itag string `json:"itag"` Type string `json:"type"` Quality string `json:"quality"` Container string `json:"container"` Encoding string `json:"encoding"` QualityLabel string `json:"qualityLabel"` Resolution string `json:"resolution"` Size string `json:"size"` } `json:"formatStreams"` Captions []struct { Label string `json:"label"` LanguageCode string `json:"languageCode"` Url string `json:"url"` } `json:"captions"` RecommendedVideos []struct { VideoId string `json:"videoId"` Title string `json:"title"` VideoThumbnails []struct { Quality string `json:"quality"` Url string `json:"url"` Width int32 `json:"width"` Height int32 `json:"height"` } `json:"videoThumbnails"` Author string `json:"author"` LengthSeconds int32 `json:"lengthSeconds"` ViewCountText string `json:"viewCountText"` } }
VideosResponse is the structure returned when calling "Videos()"