Guten Tag, Chabrawitscher! Artikel für Anfänger, einige neue Ideen, die Sie hier nicht sehen werden. Und diese Funktionalität wurde höchstwahrscheinlich Dutzende Male in verschiedenen Sprachen implementiert. Die Idee ist, dass Sie, wenn Sie einen Link zu einem Beitrag auf Twitter erhalten, der ein Video enthält, dieses Video aufheben und in mkv konvertieren.
Zur Sache!
Was wir brauchen:
- GO
- ffmpeg
- Docker (obwohl es ohne es möglich ist. Aber wo ohne es heutzutage?!;)
Wir haben einen Link zu einem Tweet aus dem Video:
https://twitter.com/FunnyVines/status/1101196533830041600
Von der gesamten Verknüpfung interessiert uns nur die ID, die aus Zahlen besteht, daher ziehen wir die gesamte digitale Teilzeichenfolge mit einer elementaren Regelmäßigkeit heraus:
var reurl = regexp.MustCompile(`\/(\d*)$`)
Gehen Sie mit der empfangenen ID zu der Adresse:
resp, err := client.Get("https://twitter.com/i/videos/tweet/" + id)
Woher bekommen wir den Link zum JS-Code des Video-Players:
src="https://abs.twimg.com/web-video-player/TwitterVideoPlayerIframe.f52b5b572446290e.js"
Aus dieser js-Datei benötigen wir eine sehr wichtige Sache - Träger für die Autorisierung in Twitter API.
Regex'pee ihn!
re, _ := regexp.Compile(`(?m)authorization:\"Bearer (.*)\",\"x-csrf`)
Dies reicht nicht aus, um auf die API zuzugreifen. Sie benötigen dennoch guest_token. Sie können eine POST-Anfrage an die Adresse " https://api.twitter.com/1.1/guest/activate.json " senden, die dort übergeben wird: personalization_id und guest_id aus dem Cookie (das wir in der Antwort vom Server beim Zugriff auf die vorherige erhalten haben) 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 } }
guest_tokenEs ändert sich regelmäßig, ich habe nicht verstanden, wie oft es aufgerufen werden soll (vielmehr ändert sich der Timer - ein 15-Minuten-Intervall), aber es scheint, als ob Sie durch regelmäßige Aktivierung von /1.1/guest/activate.json das API-Limit für 300 Anfragen umgehen können.
Die Antwort ist gzip, es kann in Go entpackt werden, ungefähr so:
res, err := gzip.NewReader(resp.Body) if err != nil { return "", err } defer res.Close() r, err := ioutil.ReadAll(res)
Nun, das ist es! Jetzt haben wir alles, was wir brauchen, um die API aufzurufen:
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)
Die Antwort von der API lautet Json mit einer Beschreibung des Videos und vor allem der URL, über die es empfangen werden soll (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"
Und schließlich haben wir die Videoadresse, wir senden sie an ffmpeg, während wir prüfen, in welchem Videoformat ich 2 mögliche Formate gesehen habe, das erste ist 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 }
Und die zweite ist die m3u8- Wiedergabelistendatei. Für diese Option ist ein weiterer Schritt erforderlich - wir erhalten GET
ihn, und nehmen Sie die URL des Inhalts in der gewünschten Auflösung:
#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
Und trotzdem - ffmpeg.
Und jetzt ein wenig zum HTTP-Server
Ich habe verwendet:
Die Logik ist wie folgt, wir starten den 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) }
Und wir verarbeiten nur eine Route / * Video:
Wie kann das alles gesammelt werden?
Zum Beispiel ein einfaches Makefile (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
Achten Sie auf das Flag "-v / etc / ssl: / etc / ssl: ro", im Basis-Image ubuntu gab es keine Root-Zertifikate und der http-Client erkannte https Twitter nicht, warf es vom Host-Computer über --volume (jetzt wie) wie, es ist korrekter, --mount zu verwenden).
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
Zweifellos habe ich Amerika in diesem Artikel nicht entdeckt, aber plötzlich wird es für jemanden nützlich sein.
Quellen finden Sie hier .