8000 download cmd handles playlist & video by itscaro · Pull Request #178 · kkdai/youtube · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

download cmd handles playlist & video #178

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
8000 Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ func (c *Client) GetPlaylist(url string) (*Playlist, error) {
// for these videos. Playlist entries cannot be downloaded, as they lack all the required metadata, but
// can be used to enumerate all IDs, Authors, Titles, etc.
func (c *Client) GetPlaylistContext(ctx context.Context, url string) (*Playlist, error) {
id, err := extractPlaylistID(url)
id, err := ExtractPlaylistID(url)
if err != nil {
return nil, fmt.Errorf("extractPlaylistID failed: %w", err)
}
Expand Down
54 changes: 49 additions & 5 deletions cmd/youtubedr/download.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,65 @@ import (
"fmt"
"log"
"os/exec"
"strconv"
"strings"

"github.com/kkdai/youtube/v2"
"github.com/spf13/cobra"
)

var (
errNotID = fmt.Errorf("cannot detect ID in given input")
)

// downloadCmd represents the download command
var downloadCmd = &cobra.Command{
Use: "download",
Short: "Downloads a video from youtube",
Short: "Downloads a video or a playlist from youtube",
Example: `youtubedr -o "Campaign Diary".mp4 https://www.youtube.com/watch\?v\=XbNghLqsVwU`,
Args: cobra.ExactArgs(1),
Run: func(cmd *cobra.Command, args []string) {
exitOnError(download(args[0]))
if playlistID, err := youtube.ExtractPlaylistID(args[0]); err != nil {
videoID, err := youtube.ExtractVideoID(args[0])
if err != nil {
exitOnError(errNotID)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please try to keep the code more on the left. You don't need the else if you write instead:

videoID, err := youtube.ExtractVideoID(args[0])
if err != nil {
	exitOnError(errN
10000
otID)
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@corny modifed, could you have a look?

}
log.Printf(
"download video %s to directory %s\n",
videoID,
outputDir,
)
exitOnError(download(videoID))
} else {
playlist, err := getDownloader().GetPlaylist(playlistID)
if err != nil {
exitOnError(err)
}
log.Printf(
"download %d videos from playlist %s to directory %s\n",
len(playlist.Videos),
playlist.ID,
outputDir,
)
var errors []error
outputFileOrigin := outputFile
for i, v := range playlist.Videos {
if len(outputFileOrigin) != 0 {
index := v.Index
if len(index) == 0 {
// In case video does not contain index
index = strconv.Itoa(i)
}
outputFile = fmt.Sprintf("%s-%s", outputFile, index)
}
if err := download(v.ID); err != nil {
errors = append(errors, err)
}
}
if len(errors) > 0 {
exitOnErrors(errors)
}
}
},
}

Expand All @@ -30,7 +76,7 @@ var (
func init() {
rootCmd.AddCommand(downloadCmd)

downloadCmd.Flags().StringVarP(&outputFile, "filename", "o", "", "The output file, the default is genated by the video title.")
downloadCmd.Flags().StringVarP(&outputFile, "filename", "o", "", "The output file, the default is generated from the video title.")
downloadCmd.Flags().StringVarP(&outputDir, "directory", "d", ".", "The output directory.")
addQualityFlag(downloadCmd.Flags())
addMimeTypeFlag(downloadCmd.Flags())
Expand All @@ -42,8 +88,6 @@ func download(id string) error {
return err
}

log.Println("download to directory", outputDir)

if strings.HasPrefix(outputQuality, "hd") {
if err := checkFFMPEG(); err != nil {
return err
Expand Down
9 changes: 9 additions & 0 deletions cmd/youtubedr/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,12 @@ func exitOnError(err error) {
os.Exit(1)
}
}

func exitOnErrors(errors []error) {
for _, err := range errors {
fmt.Fprintln(os.Stderr, err)
}
if len(errors) != 0 {
os.Exit(1)
}
}
21 changes: 16 additions & 5 deletions playlist.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,13 @@ type Playlist struct {

type PlaylistEntry struct {
ID string
Index string
Title string
Author string
Duration time.Duration
}

func extractPlaylistID(url string) (string, error) {
func ExtractPlaylistID(url string) (string, error) {
if playlistIDRegex.Match([]byte(url)) {
return url, nil
}
Expand Down Expand Up @@ -128,10 +129,11 @@ func (p *Playlist) UnmarshalJSON(b []byte) (err error) {

type videosJSONExtractor struct {
Renderer *struct {
ID string `json:"videoId"`
Title withRuns `json:"title"`
Author withRuns `json:"shortBylineText"`
Duration string `json:"lengthSeconds"`
ID string `json:"videoId"`
Index indexText `json:"index"`
Title withRuns `json:"title"`
Author withRuns `json:"shortBylineText"`
Duration string `json:"lengthSeconds"`
} `json:"playlistVideoRenderer"`
}

Expand All @@ -142,6 +144,7 @@ func (vje videosJSONExtractor) PlaylistEntry() *PlaylistEntry {
}
return &PlaylistEntry{
ID: vje.Renderer.ID,
Index: vje.Renderer.Index.String(),
Title: vje.Renderer.Title.String(),
Author: vje.Renderer.Author.String(),
Duration: time.Second * time.Duration(ds),
Expand All @@ -154,9 +157,17 @@ type withRuns struct {
} `json:"runs"`
}

type indexText struct {
SimpleText string `json:"simpleText"`
}

func (wr withRuns) String() string {
if len(wr.Runs) > 0 {
return wr.Runs[0].Text
}
return ""
}

func (it indexText) String() string {
return it.SimpleText
}
2 changes: 1 addition & 1 deletion playlist_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ func TestYoutube_extractPlaylistID(t *testing.T) {

for _, v := range tests {
t.Run(v.name, func(t *testing.T) {
id, err := extractPlaylistID(v.url)
id, err := ExtractPlaylistID(v.url)

assert.Equal(t, v.expectedError, err)
assert.Equal(t, v.expectedID, id)
Expand Down
0