Microservice on GO untuk mengambil video dari tweet

Selamat siang, Khabravchians! Artikel untuk pemula, semacam ide baru yang tidak akan Anda lihat di sini. Dan fungsi ini, kemungkinan besar, diimplementasikan puluhan kali dalam berbagai bahasa. Idenya adalah bahwa jika Anda mendapatkan tautan ke pos di Twitter yang berisi video, ambil video ini dan konversikan ke mkv.


Untuk bisnis!


Apa yang kita butuhkan:


  • GO
  • ffmpeg
  • buruh pelabuhan (meskipun mungkin tanpa itu. Namun, di mana tanpa itu hari ini?!;)

Kami memiliki tautan ke tweet dari video:


https://twitter.com/FunnyVines/status/1101196533830041600 

Dari seluruh tautan, kami hanya tertarik pada ID yang terdiri dari angka-angka, jadi kami menarik seluruh substring digital dengan keteraturan dasar:


 var reurl = regexp.MustCompile(`\/(\d*)$`) //   -  e.GET("/*video", func(c *fasthttp.RequestCtx) { //      url := reurl.FindSubmatch([]byte(c.UserValue("video").(string))) 

Dengan ID yang diterima, buka alamat:


 resp, err := client.Get("https://twitter.com/i/videos/tweet/" + id) 

Di mana kami mendapatkan tautan ke kode pemutar video JS:


src="https://abs.twimg.com/web-video-player/TwitterVideoPlayerIframe.f52b5b572446290e.js"
Dari file js ini kita perlu satu hal yang sangat penting - pembawa untuk otorisasi di twitter api.


Terima kasih dia!


 re, _ := regexp.Compile(`(?m)authorization:\"Bearer (.*)\",\"x-csrf`) 

Ini tidak cukup untuk mengakses api, Anda masih perlu guest_token. Itu dapat diperoleh dengan menerapkan permintaan POST ke alamat - " https://api.twitter.com/1.1/guest/activate.json ", lewat di sana: personalisasi_id dan guest_id dari cookie (yang kami terima dalam respons dari server ketika mengakses yang sebelumnya URL):


  var personalization_id, guest_id string cookies := resp.Cookies() for _, cookie := range cookies { if cookie.Name == "personalization_id" { personalization_id = cookie.Value } if cookie.Name == "guest_id" { guest_id = cookie.Value } } // // Get Activation url, _ := url.Parse("https://api.twitter.com/1.1/guest/activate.json") request := &http.Request{ Method: "POST", URL: url, Header: http.Header{ "user-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"}, "accept-encoding": []string{"gzip", "deflate", "br"}, "authorization": []string{"Bearer " + bearer}, "cookie": []string{"personalization_id=\"" + personalization_id + "\"; guest_id=" + guest_id} }, } resp, err = client.Do(request) 

guest_token

Ini berubah secara berkala, saya tidak mengerti seberapa sering menyebutnya (lebih tepatnya, itu berubah dalam timer - interval 15 menit), tetapi sepertinya aktivasi reguler dari /1.1/guest/activate.json memungkinkan Anda untuk memotong batas api untuk 300 permintaan.


Jawabannya adalah gzip, bisa dibongkar di Go, kira-kira seperti ini:


 res, err := gzip.NewReader(resp.Body) if err != nil { return "", err } defer res.Close() r, err := ioutil.ReadAll(res) 

Yah, itu dia! Sekarang kami memiliki semua yang kami butuhkan untuk memanggil API:


  url, _ = url.Parse("https://api.twitter.com/1.1/videos/tweet/config/" + id + ".json") request = &http.Request{ Method: "GET", URL: url, Header: http.Header{ "user-agent": []string{"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"}, "accept-encoding": []string{"gzip", "deflate", "br"}, "origin": []string{"https://twitter.com"}, "x-guest-token": []string{gt.GuestToken}, "referer": []string{"https://twitter.com/i/videos/tweet/" + id}, "authorization": []string{"Bearer " + bearer}}, } resp, err = client.Do(request) 

Respons dari API adalah Json dengan deskripsi video, dan yang paling penting, URL untuk menerimanya (playbackUrl):


 {"contentType":"media_entity","publisherId":"4888096512","contentId":"1096941371649347584","durationMs":11201,"playbackUrl":"https:\/\/video.twimg.com\/ext_tw_video\/1096941371649347584\/pu\/pl\/xcBvPmwAmKckck-F.m3u8?tag=6","playbackType" 

Dan akhirnya, kami memiliki alamat video, kami mengirimkannya ke ffmpeg, sambil memeriksa format video yang saya lihat 2 format yang mungkin, yang pertama adalah mp4:


 if strings.Contains(videoURL.Track.PlaybackURL, ".mp4") { convert := exec.Command("ffmpeg", "-i", videoURL.Track.PlaybackURL, "-c", "copy", "./videos/"+id+".mkv") convert.Stdout = os.Stdout convert.Stderr = os.Stderr if convert.Run() != nil { return "", err } return id, nil } 

Dan yang kedua adalah file playlist m3u8 , untuk opsi ini diperlukan satu langkah lagi - kita mendapatkan GET
dia, dan ambil URL konten dalam resolusi yang diinginkan:


 #EXT-X-INDEPENDENT-SEGMENTS #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=256000,RESOLUTION=180x316,CODECS="mp4a.40.2,avc1.4d0015" /ext_tw_video/1039516210948333568/pu/pl/180x316/x0HWMgnbSJ9y6NFL.m3u8 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=832000,RESOLUTION=464x816,CODECS="mp4a.40.2,avc1.4d001f" /ext_tw_video/1039516210948333568/pu/pl/464x816/Z58__ptq1xBk8CIV.m3u8 

Dan masih - ffmpeg.


Dan sekarang, sedikit tentang server HTTP


Saya menggunakan:



Logikanya adalah sebagai berikut, kita mulai server:


 cfg := tcplisten.Config{ ReusePort: true, FastOpen: true, DeferAccept: true, Backlog: 1024, } ln, err := cfg.NewListener("tcp4", ":8080") if err != nil { log.Fatalf("error in reuseport listener: %s\n", err) } serv := fasthttp.Server{Handler: e.Handler, ReduceMemoryUsage: false, Name: "highload", Concurrency: 2 * 1024, DisableHeaderNamesNormalizing: true} if err := serv.Serve(ln); err != nil { log.Fatalf("error in fasthttp Server: %s", err) } 

Dan kami hanya memproses satu rute / * video:


 //  : //  http://localhost:8080/https://twitter.com/FunnyVines/status/1101196533830041600 //   http://localhost:8080/1101196533830041600 e.GET("/*video", func(c *fasthttp.RequestCtx) { 

Bagaimana semua ini bisa dikumpulkan?


Misalnya, Makefile sederhana (make build, make run ...):


 build: go build -o main docker build -t tvideo . run: go build -o main docker build -t tvideo . docker kill tvideo docker run -d --rm --name tvideo -v /etc/ssl:/etc/ssl:ro -v videos:/opt/videos -p 8080:8080 tvideo docker logs -f tvideo 

Perhatikan bendera "-v / etc / ssl: / etc / ssl: ro", di gambar dasar ubuntu tidak ada sertifikat root dan klien http tidak mengenali https twitter, melemparkannya dari mesin host melalui --volume (sekarang, seperti caranya, lebih tepat menggunakan --mount ).


Dockerfile


 FROM ubuntu //     docker image COPY main /opt/app RUN apt-get update && \ //   apt-get install -y ffmpeg && \ chmod +x /opt/app EXPOSE 8080 WORKDIR /opt CMD ./app 

Tidak diragukan lagi, saya tidak menemukan Amerika di artikel ini, tetapi tiba-tiba itu akan berguna bagi seseorang.


Sumber tersedia di sini .

Source: https://habr.com/ru/post/id442096/


All Articles