Add backend support for importing youtube videos

This commit is contained in:
James Mills 2020-03-27 14:54:48 +10:00
parent 00ecbee8b9
commit 10a5f82498
No known key found for this signature in database
GPG key ID: AC4C014F1440EBD6
4 changed files with 175 additions and 169 deletions

View file

@ -19,6 +19,7 @@ import (
"github.com/gorilla/handlers"
"github.com/gorilla/mux"
"github.com/renstrom/shortuuid"
"github.com/rylio/ytdl"
log "github.com/sirupsen/logrus"
"github.com/wybiral/tube/media"
"github.com/wybiral/tube/utils"
@ -325,96 +326,112 @@ func (a *App) importHandler(w http.ResponseWriter, r *http.Request) {
keys = append(keys, k)
}
sort.Strings(keys)
//collection := keys[0]
collection := keys[0]
/*
uf, err := ioutil.TempFile(
a.Config.Server.UploadPath,
fmt.Sprintf("tube-import-*%s.mp4",
)
if err != nil {
err := fmt.Errorf("error creating temporary file for importing: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer os.Remove(uf.Name())
vid, err := ytdl.GetVideoInfo(url)
if err != nil {
err := fmt.Errorf("error retriving video info for %s: %w", url, err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
_, err = io.Copy(uf, file)
if err != nil {
err := fmt.Errorf("error writing file: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
uf, err := ioutil.TempFile(
a.Config.Server.UploadPath,
fmt.Sprintf("tube-import-*.mp4"),
)
if err != nil {
err := fmt.Errorf("error creating temporary file for importing: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
defer os.Remove(uf.Name())
tf, err := ioutil.TempFile(
a.Config.Server.UploadPath,
fmt.Sprintf("tube-transcode-*.mp4"),
)
if err != nil {
err := fmt.Errorf("error creating temporary file for transcoding: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
err = vid.Download(vid.Formats[0], uf)
if err != nil {
err := fmt.Errorf("error downloading video %s: %w", url, err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
vf := filepath.Join(
a.Library.Paths[collection].Path,
fmt.Sprintf("%s.mp4", shortuuid.New()),
)
thumbFn1 := fmt.Sprintf("%s.jpg", strings.TrimSuffix(tf.Name(), filepath.Ext(tf.Name())))
thumbFn2 := fmt.Sprintf("%s.jpg", strings.TrimSuffix(vf, filepath.Ext(vf)))
tf, err := ioutil.TempFile(
a.Config.Server.UploadPath,
fmt.Sprintf("tube-transcode-*.mp4"),
)
if err != nil {
err := fmt.Errorf("error creating temporary file for transcoding: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
// TODO: Use a proper Job Queue and make this async
if err := utils.RunCmd(
a.Config.Transcoder.Timeout,
"ffmpeg",
"-y",
"-i", uf.Name(),
"-vcodec", "h264",
"-acodec", "aac",
"-strict", "-2",
"-loglevel", "quiet",
tf.Name(),
); err != nil {
err := fmt.Errorf("error transcoding video: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
vf := filepath.Join(
a.Library.Paths[collection].Path,
fmt.Sprintf("%s.mp4", shortuuid.New()),
)
thumbFn1 := fmt.Sprintf("%s.jpg", strings.TrimSuffix(tf.Name(), filepath.Ext(tf.Name())))
thumbFn2 := fmt.Sprintf("%s.jpg", strings.TrimSuffix(vf, filepath.Ext(vf)))
if err := utils.RunCmd(
a.Config.Thumbnailer.Timeout,
"mt",
"-b",
"-s",
"-n", "1",
tf.Name(),
); err != nil {
err := fmt.Errorf("error generating thumbnail: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
thumbURL := vid.GetThumbnailURL(ytdl.ThumbnailQualityHigh)
res, err := http.Get(thumbURL.String())
if err != nil {
err := fmt.Errorf("error downloading thumbnail: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
thumbData, err := ioutil.ReadAll(res.Body)
res.Body.Close()
if err != nil {
err := fmt.Errorf("error reading thumbnail data: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := os.Rename(thumbFn1, thumbFn2); err != nil {
err := fmt.Errorf("error renaming generated thumbnail: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := ioutil.WriteFile(thumbFn1, thumbData, 0644); err != nil {
err := fmt.Errorf("error writing thumbnail data: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := os.Rename(tf.Name(), vf); err != nil {
err := fmt.Errorf("error renaming transcoded video: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Video successfully uploaded!")
*/
// TODO: Use a proper Job Queue and make this async
if err := utils.RunCmd(
a.Config.Transcoder.Timeout,
"ffmpeg",
"-y",
"-i", uf.Name(),
"-vcodec", "h264",
"-acodec", "aac",
"-strict", "-2",
"-loglevel", "quiet",
"-metadata", fmt.Sprintf("title=\"%s\"", vid.Title),
"-metadata", fmt.Sprintf("description=\"%s\"", vid.Description),
tf.Name(),
); err != nil {
err := fmt.Errorf("error transcoding video: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Not Implemented (yet)")
if err := os.Rename(thumbFn1, thumbFn2); err != nil {
err := fmt.Errorf("error renaming generated thumbnail: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
if err := os.Rename(tf.Name(), vf); err != nil {
err := fmt.Errorf("error renaming transcoded video: %w", err)
log.Error(err)
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
fmt.Fprintf(w, "Video successfully imported!")
} else {
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
}

File diff suppressed because one or more lines are too long

3
go.mod
View file

@ -19,6 +19,7 @@ require (
github.com/mutschler/mt v0.0.0-20200120124658-d48aed259ff6 // indirect
github.com/prologic/bitcask v0.3.5
github.com/renstrom/shortuuid v3.0.0+incompatible
github.com/rylio/ytdl v0.6.2
github.com/sirupsen/logrus v1.4.2
github.com/spf13/pflag v1.0.5
github.com/spf13/viper v1.6.2 // indirect
@ -27,5 +28,5 @@ require (
gitlab.com/opennota/screengen v0.0.0-20191122132138-74a8d677a1a5 // indirect
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4
golang.org/x/net v0.0.0-20190628185345-da137c7871d7
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa
golang.org/x/sys v0.0.0-20191104094858-e8c54fb511f6
)

20
go.sum
View file

@ -31,6 +31,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/daaku/go.zipexe v1.0.0 h1:VSOgZtH418pH9L16hC/JrgSNJbbAL26pj7lmD1+CGdY=
github.com/daaku/go.zipexe v1.0.0/go.mod h1:z8IiR6TsVLEYKwXAoE/I+8ys/sDkgTzSL0CLnGVd57E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -106,6 +107,8 @@ github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcncea
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84=
github.com/mattn/go-runewidth v0.0.6/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@ -118,6 +121,7 @@ github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRW
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229 h1:E2B8qYyeSgv5MXpmzZXRNp8IAQ4vjxIjhpAf5hv/tAg=
github.com/nkovacs/streamquote v0.0.0-20170412213628-49af9bddb229/go.mod h1:0aYXnNPJ8l7uZxf45rWW1a/uME32OF0rhiYGNQ2oF2E=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
@ -144,8 +148,15 @@ github.com/renstrom/shortuuid v3.0.0+incompatible h1:F6T1U7bWlI3FTV+JE8HyeR7bkTe
github.com/renstrom/shortuuid v3.0.0+incompatible/go.mod h1:n18Ycpn8DijG+h/lLBQVnGKv1BCtTeXo8KKSbBOrQ8c=
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
github.com/rs/zerolog v1.16.0 h1:AaELmZdcJHT8m6oZ5py4213cdFK8XGXkB3dFdAQ+P7Q=
github.com/rs/zerolog v1.16.0/go.mod h1:9nvC1axdVrAHcu/s9taAVfBuIdTZLVQmKQyvrUjF5+I=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rylio/ytdl v0.6.2 h1:ZYzaoUqAniH/yb7yscdWlVoecVRcvpFDgS15NyDTZQA=
github.com/rylio/ytdl v0.6.2/go.mod h1:F0WX8szfQ00mhmfla+0xVJp483SBV4VO/ByUaNioNSM=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
@ -176,6 +187,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tidwall/redcon v1.0.0/go.mod h1:bdYBm4rlcWpst2XMwKVzWDF9CoUxEbUmM7CQrKeOZas=
@ -186,6 +198,7 @@ github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKw
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1 h1:tY9CJiPnMXf1ERmG2EyK7gNUd+c6RKGD0IfU8WdUSz8=
@ -198,6 +211,7 @@ github.com/xfrr/goffmpeg v0.0.0-20191120110122-53b0a69281d4 h1:iuT6IHMZMFQ8vZ67/
github.com/xfrr/goffmpeg v0.0.0-20191120110122-53b0a69281d4/go.mod h1:mL+qPvJWwu9An5a66+HyEJ7X7iEUSI09zX/Xl67XRXs=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q=
gitlab.com/opennota/screengen v0.0.0-20191122132138-74a8d677a1a5 h1:Ne2t4aWWPqzcLcDBQRHCn8pgOl3+z9yXDFK4XgNXts0=
gitlab.com/opennota/screengen v0.0.0-20191122132138-74a8d677a1a5/go.mod h1:4kED4yriw2zslwYmXFCa5qCvEKwleBA7l5OE+d94NTU=
go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
@ -234,6 +248,7 @@ golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAG
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -248,6 +263,9 @@ golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb h1:fgwFCsaw9buMuxNd6+DQfAuSF
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa h1:KIDDMLT1O0Nr7TSxp8xM5tJcdn8tgyAONntO829og1M=
golang.org/x/sys v0.0.0-20190804053845-51ab0e2deafa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191104094858-e8c54fb511f6 h1:ZJUmhYTp8GbGC0ViZRc2U+MIYQ8xx9MscsdXnclfIhw=
golang.org/x/sys v0.0.0-20191104094858-e8c54fb511f6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
@ -258,6 +276,8 @@ golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190828213141-aed303cbaa74/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=