giffer

Create .gif images from sites like youtube.com
Log | Files | Refs | LICENSE

download.go (1886B)


      1 package giffer
      2 
      3 import (
      4 	"context"
      5 	"fmt"
      6 	"io"
      7 	"os"
      8 	"path/filepath"
      9 
     10 	"github.com/OneOfOne/xxhash"
     11 	"github.com/kkdai/youtube/v2"
     12 	"github.com/kkdai/youtube/v2/downloader"
     13 	"github.com/pkg/errors"
     14 )
     15 
     16 // Downloader is responsible for downloading videos.
     17 type Downloader struct {
     18 	Dir    string
     19 	FFmpeg string
     20 	Debug  bool
     21 	Out    io.Writer
     22 }
     23 
     24 // Download the video from URL into Dir and return the full path to the
     25 // downloaded file.
     26 func (dl Downloader) Download(
     27 	URL string,
     28 	start, end float64,
     29 ) (string, error) {
     30 	dl.logf("ffmpeg: %q\n", dl.FFmpeg)
     31 	h, err := hash(fmt.Sprintf("%s_%f_%f", URL, start, end))
     32 	if err != nil {
     33 		return "", errors.Wrap(err, "creating hash")
     34 	}
     35 	dir := filepath.Join(dl.Dir, h)
     36 	if err := os.MkdirAll(dir, 0755); err != nil && !os.IsExist(err) {
     37 		return "", errors.Wrap(err, "preparing directories")
     38 	}
     39 	tmp, err := dl.download(URL, start, end)
     40 	if err != nil {
     41 		return "", err
     42 	}
     43 	real := filepath.Join(dir, h+filepath.Ext(tmp))
     44 	if err := os.Rename(tmp, real); err != nil {
     45 		return "", errors.Wrap(err, "renaming temporary file")
     46 	}
     47 	return real, nil
     48 }
     49 
     50 func (dl Downloader) logf(f string, v ...interface{}) {
     51 	if !dl.Debug || dl.Out == nil {
     52 		return
     53 	}
     54 	fmt.Fprintf(dl.Out, f, v...)
     55 }
     56 
     57 // download a video from the specified url.
     58 func (dl Downloader) download(
     59 	videoURL string,
     60 	start, end float64,
     61 ) (string, error) {
     62 	d := downloader.Downloader{
     63 		Client: youtube.Client{},
     64 	}
     65 	v, err := d.GetVideo(videoURL)
     66 	if err != nil {
     67 		return "", fmt.Errorf("getting video: %w", err)
     68 	}
     69 	outf := filepath.Join(os.TempDir(), downloader.SanitizeFilename(v.Title))
     70 	return outf, d.Download(context.TODO(), v, &v.Formats[0], outf)
     71 }
     72 
     73 func hash(input string) (string, error) {
     74 	h := xxhash.New64()
     75 	if _, err := h.WriteString(input); err != nil {
     76 		return "", errors.Wrap(err, "writing to hash object")
     77 	}
     78 	return fmt.Sprintf("%d", h.Sum64()), nil
     79 }