[curl] ściągnięcie pliku mp4 i zapisanie go w mniejszej rozdzielczości

W jednym ze swoich poprzednich tematów pytałem o możliwość pobrania pliku mp4 z serwisu, który nie udostępnia bezpośredniego linka do niego. Otrzymałem wówczas poradę, jak zrobić to przy użyciu curl’a, która działa znakomicie. Chciałbym teraz zapytać, czy przy użyciu tej samej metody da się ściągnąć plik mp4 i zapisać go w rozdzielczości mniejszej niż oryginalna. Np. plik 1080p zapisać jako 720p.

Puść go przez ffmpeg :slight_smile:

@hindus, weźmy taki przykład:

curl 'https://stream.vider.info/video/263523/v.mp4?uid=0' \
  -H 'authority: stream.vider.info' \
  -H 'accept: */*' \
  -H 'accept-language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7' \
  -H 'cookie: _ga=GA1.1.1754579214.1666461710; euconsent-v2=CPhP_kAPhP_kAAKAsAPLCmCsAP_AAH_AAB5YJFNd_H__bW9r-f5_aft0eY1P9_r37uQzDhfNk-8F3L_W_LwX52E7NF36tq4KmR4ku1LBIUNlHMHUDUmwaokVryHsak2cpzNKJ7BEknMZOydYGF9vmxtj-QKY7_5_d3bx2D-t_9v239z3z81Xn3d53-_03LCdV5_9Dfn9fR_bc9KPt_58v8v8_____3_e__3_7997BIgAkw1biALsyxwZtAwigRAjCsJCqBQAQUAwtEBgA4OCnZWAT6wgQAIBQBGBECHAFGBAIAABIAkIgAkCLBAAACIBAACABEIhAAwMAgsALAwCAAEA0DFEKAAQJCDIgIilMCAqBIIDWyoQSgukNMIA6ywAoJEbFQAIgkBFYAAgLBwDBEgJWLBAkxRvkAIwQoBRKhWogAAA.YAAAAAAAAAAA; addtl_consent=1~39.4.3.9.6.9.13.6.4.15.9.5.2.7.4.1.7.1.3.2.10.3.5.4.21.4.6.9.7.10.2.9.2.18.7.6.14.5.20.6.5.1.3.1.11.29.4.14.4.5.3.10.6.2.9.6.6.9.4.4.29.4.5.3.1.6.2.2.17.1.17.10.9.1.8.6.2.8.3.4.146.8.42.15.1.14.3.1.8.10.25.3.7.25.5.18.9.7.41.2.4.18.21.3.4.2.7.6.5.2.14.18.7.3.2.2.8.20.8.8.6.3.10.4.20.2.13.4.6.4.11.1.3.22.16.2.6.8.2.4.11.6.5.33.11.8.1.10.28.12.1.3.21.2.7.6.1.9.30.17.4.9.15.8.7.3.6.6.7.2.4.1.7.12.13.22.13.2.12.2.10.1.4.15.2.4.9.4.5.4.7.13.5.15.4.13.4.14.8.2.15.2.5.6.2.2.1.2.14.7.4.8.2.9.10.18.12.13.2.18.1.1.3.1.1.9.25.4.1.19.8.4.5.3.5.4.8.4.2.2.2.14.2.13.4.2.6.9.6.3.4.3.5.2.3.6.10.11.6.3.16.3.11.3.1.2.3.9.19.11.15.3.10.7.6.4.3.4.6.3.3.3.3.1.1.1.6.11.3.1.1.11.6.1.10.5.2.6.3.2.2.4.3.2.2.7.15.7.12.2.1.3.3.4.5.4.3.2.2.5.3.1.1.1.2.9.1.6.9.1.5.2.1.7.10.11.1.3.1.1.2.1.3.2.6.1.12.5.3.1.3.1.1.2.2.7.7.1.4.1.2.6.1.2.1.1.3.1.1.4.1.1.2.1.8.1.7.4.3.2.1.3.5.3.9.6.1.15.10.28.1.2.2.12.3.4.1.6.3.4.7.1.3.1.1.3.1.5.3.1.3.4.1.1.4.2.1.2.1.2.2.2.4.2.1.2.2.2.4.1.1.1.2.2.1.1.1.1.2.1.1.1.2.2.1.1.2.1.2.1.7.1.2.1.1.1.2.1.1.1.1.2.1.1.3.2.1.1.8.1.1.6.2.1.6.5.1.1.1.1.1.2.2.3.1.1.4.1.1.2.2.1.1.4.3.1.2.2.1.2.1.2.3.1.1.2.4.1.1.1.5.1.3.6.3.1.5.2.3.4.1.2.3.1.4.2.1.2.2.2.1.1.1.1.1.1.11.1.3.1.1.2.2.5.2.3.3.5.1.1.1.4.2.1.1.2.5.1.9.4.1.1.3.1.7.1.4.5.1.7.2.1.1.1.2.1.1.1.4.2.1.12.1.1.3.1.2.2.3.1.2.1.1.1.2.1.1.2.1.1.1.1.2.4.1.5.1.2.4.3.8.2.2.9.7.2.2.1.2.1.4.6.1.1.6.1.1.2.6.3.1.2; cookie_v12stream_hostname=freedisc-n5; cookie_v12viderinfoo12_sessions=a%3A7%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%227e3b579ac642eca6fce8ec745dde3ee4%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A10%3A%2283.4.15.40%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A110%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F106.0.0.0+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1666615692%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A8%3A%22language%22%3Bs%3A2%3A%22pl%22%3Bs%3A14%3A%22file_last_view%22%3Bs%3A6%3A%22263521%22%3B%7D3d1ef64a986acc87e6c910a9fc7a462a; cookie_v12last_item_id=263523; cookie_v12sess_ebdd=YToxOntzOjQ6InRpbWUiO2k6MTY2NjYxNTkzMzt9; _ga_VP1P70Q01K=GS1.1.1666611426.2.1.1666615933.0.0.0; _ga_3YMP2VEBVF=GS1.1.1666611426.2.1.1666615933.0.0.0' \
  -H 'range: bytes=0-' \
  -H 'referer: https://vider.info/' \
  -H 'sec-ch-ua: "Chromium";v="106", "Google Chrome";v="106", "Not;A=Brand";v="99"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "Windows"' \
  -H 'sec-fetch-dest: video' \
  -H 'sec-fetch-mode: no-cors' \
  -H 'sec-fetch-site: same-site' \
  -H 'user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36' \
  --compressed -o /home/rostov/domains/rostov.smallhost.pl/public_html/seriale/S01E04.mp4 &>/dev/null &

Jak powinienem to zrobić?

Tak naprawdę musisz przekodować cały materiał. Dokładnie najlepiej ffmpeg ale nie poprzez potok z curl tylko wykorzystując wewnętrzną obsługę http w ffmpeg, czyli musisz przerobić nagłówki na postać zrozumiałą dla ffmpeg (zwróć uwagę na zapis, w ffmpeg podajesz nagłówki w jednym parametrze, ffmpeg jest bardzo wrażliwy np na dodatkowe puste linie podane w -headers, wtedy odmawia współpracy) :

ffmpeg -headers $'authority: stream.vider.info
	accept: */*
	accept-language: pl-PL,pl;q=0.9,en-US;q=0.8,en;q=0.7
	cookie: _ga=GA1.1.1754579214.1666461710; euconsent-v2=CPhP_kAPhP_kAAKAsAPLCmCsAP_AAH_AAB5YJFNd_H__bW9r-f5_aft0eY1P9_r37uQzDhfNk-8F3L_W_LwX52E7NF36tq4KmR4ku1LBIUNlHMHUDUmwaokVryHsak2cpzNKJ7BEknMZOydYGF9vmxtj-QKY7_5_d3bx2D-t_9v239z3z81Xn3d53-_03LCdV5_9Dfn9fR_bc9KPt_58v8v8_____3_e__3_7997BIgAkw1biALsyxwZtAwigRAjCsJCqBQAQUAwtEBgA4OCnZWAT6wgQAIBQBGBECHAFGBAIAABIAkIgAkCLBAAACIBAACABEIhAAwMAgsALAwCAAEA0DFEKAAQJCDIgIilMCAqBIIDWyoQSgukNMIA6ywAoJEbFQAIgkBFYAAgLBwDBEgJWLBAkxRvkAIwQoBRKhWogAAA.YAAAAAAAAAAA; addtl_consent=1~39.4.3.9.6.9.13.6.4.15.9.5.2.7.4.1.7.1.3.2.10.3.5.4.21.4.6.9.7.10.2.9.2.18.7.6.14.5.20.6.5.1.3.1.11.29.4.14.4.5.3.10.6.2.9.6.6.9.4.4.29.4.5.3.1.6.2.2.17.1.17.10.9.1.8.6.2.8.3.4.146.8.42.15.1.14.3.1.8.10.25.3.7.25.5.18.9.7.41.2.4.18.21.3.4.2.7.6.5.2.14.18.7.3.2.2.8.20.8.8.6.3.10.4.20.2.13.4.6.4.11.1.3.22.16.2.6.8.2.4.11.6.5.33.11.8.1.10.28.12.1.3.21.2.7.6.1.9.30.17.4.9.15.8.7.3.6.6.7.2.4.1.7.12.13.22.13.2.12.2.10.1.4.15.2.4.9.4.5.4.7.13.5.15.4.13.4.14.8.2.15.2.5.6.2.2.1.2.14.7.4.8.2.9.10.18.12.13.2.18.1.1.3.1.1.9.25.4.1.19.8.4.5.3.5.4.8.4.2.2.2.14.2.13.4.2.6.9.6.3.4.3.5.2.3.6.10.11.6.3.16.3.11.3.1.2.3.9.19.11.15.3.10.7.6.4.3.4.6.3.3.3.3.1.1.1.6.11.3.1.1.11.6.1.10.5.2.6.3.2.2.4.3.2.2.7.15.7.12.2.1.3.3.4.5.4.3.2.2.5.3.1.1.1.2.9.1.6.9.1.5.2.1.7.10.11.1.3.1.1.2.1.3.2.6.1.12.5.3.1.3.1.1.2.2.7.7.1.4.1.2.6.1.2.1.1.3.1.1.4.1.1.2.1.8.1.7.4.3.2.1.3.5.3.9.6.1.15.10.28.1.2.2.12.3.4.1.6.3.4.7.1.3.1.1.3.1.5.3.1.3.4.1.1.4.2.1.2.1.2.2.2.4.2.1.2.2.2.4.1.1.1.2.2.1.1.1.1.2.1.1.1.2.2.1.1.2.1.2.1.7.1.2.1.1.1.2.1.1.1.1.2.1.1.3.2.1.1.8.1.1.6.2.1.6.5.1.1.1.1.1.2.2.3.1.1.4.1.1.2.2.1.1.4.3.1.2.2.1.2.1.2.3.1.1.2.4.1.1.1.5.1.3.6.3.1.5.2.3.4.1.2.3.1.4.2.1.2.2.2.1.1.1.1.1.1.11.1.3.1.1.2.2.5.2.3.3.5.1.1.1.4.2.1.1.2.5.1.9.4.1.1.3.1.7.1.4.5.1.7.2.1.1.1.2.1.1.1.4.2.1.12.1.1.3.1.2.2.3.1.2.1.1.1.2.1.1.2.1.1.1.1.2.4.1.5.1.2.4.3.8.2.2.9.7.2.2.1.2.1.4.6.1.1.6.1.1.2.6.3.1.2; cookie_v12stream_hostname=freedisc-n5; cookie_v12viderinfoo12_sessions=a%3A7%3A%7Bs%3A10%3A%22session_id%22%3Bs%3A32%3A%227e3b579ac642eca6fce8ec745dde3ee4%22%3Bs%3A10%3A%22ip_address%22%3Bs%3A10%3A%2283.4.15.40%22%3Bs%3A10%3A%22user_agent%22%3Bs%3A110%3A%22Mozilla%2F5.0+%28Windows+NT+6.1%3B+Win64%3B+x64%29+AppleWebKit%2F537.36+%28KHTML%2C+like+Gecko%29+Chrome%2F106.0.0.0+Safari%2F537.36%22%3Bs%3A13%3A%22last_activity%22%3Bi%3A1666615692%3Bs%3A9%3A%22user_data%22%3Bs%3A0%3A%22%22%3Bs%3A8%3A%22language%22%3Bs%3A2%3A%22pl%22%3Bs%3A14%3A%22file_last_view%22%3Bs%3A6%3A%22263521%22%3B%7D3d1ef64a986acc87e6c910a9fc7a462a; cookie_v12last_item_id=263523; cookie_v12sess_ebdd=YToxOntzOjQ6InRpbWUiO2k6MTY2NjYxNTkzMzt9; _ga_VP1P70Q01K=GS1.1.1666611426.2.1.1666615933.0.0.0; _ga_3YMP2VEBVF=GS1.1.1666611426.2.1.1666615933.0.0.0
	range: bytes=0-
	referer: https://vider.info/
	sec-ch-ua: "Chromium";v="106", "Google Chrome";v="106", "Not;A=Brand";v="99"
	sec-ch-ua-mobile: ?0
	sec-ch-ua-platform: "Windows"
	sec-fetch-dest: video
	sec-fetch-mode: no-cors
	sec-fetch-site: same-site
	user-agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36
	' -i https://stream.vider.info/video/263523/v.mp4?uid=0 -vf scale=1280:720 -preset slow -crf 18 output.mp4

Dobierz sobie preset oraz crf zgodnie z Encode/H.264 – FFmpeg, możesz ich nie podawać, wtedy zostaną użyte wartości domyślne.

Jeżeli na końcu podasz

-i https://stream.vider.info/video/263523/v.mp4?uid=0 -v trace

to uzyskasz informacje o wideo, zamiast konwersji. Przydatne, bo od razu widać np w jakiej rozdzielczości jest materiał źródłowy (pod linkiem, który podałeś jest film o rozdzielczości 480x272 ).

Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'https://stream.vider.info/video/263523/v.mp4?uid=0':
  Metadata:
    major_brand     : isom
    minor_version   : 512
    compatible_brands: isomiso2avc1mp41
    encoder         : Lavf55.0.100
  Duration: 00:43:41.33, start: 0.000000, bitrate: 342 kb/s
    Stream #0:0(und), 3, 1/15360: Video: h264 (High), 1 reference frame (avc1 / 0x31637661), yuv420p(left), **480x272** [SAR 34:45 DAR 4:3], 0/1, 225 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
    Metadata:
      handler_name    : VideoHandler
    Stream #0:1(pol), 1, 1/48000: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 108 kb/s (default)
    Metadata:
      handler_name    : SoundHandler

Czyli w tym przypadku wykona się skalowanie w górę z 420p do 720p co nie da żadnego zysku, a plik wynikowy będzie większy.

@Bradlee, czyli konwersja w tzw. locie całkowicie odpada?

To nawet nie jest 420p a 272p:

video - what exactly mean 2160p, 1440p, 1080p, ... 144p? - Stack Overflow

To oczywiste, że określając rozdzielczość video, podaje się ilość linii w pionie.
Używając akurat tego filmu, chciałem tylko pokazać, w jaki sposób go ściągam przy użyciu curl’a. Rozdzielczość źródła nie miała w tym przypadku znaczenia, bo wiadomo, że konwersja z mniejszej do większej przynosi pogorszenie jakości.

A to nie lepiej użyć programu HandBrake?
Możesz przekonwertować plik na format H.254 lub H.265 z kompresją i jakość pliku będzie niezauważalna a odczuwalnie mniejsza.

Program jest darmowy i ma masę możliwości,
polecam pobawić się https://handbrake.fr/

Gorzej jak antyczne CPU/GPU i będzie tylko męczyć komputer.

Nie bardzo. Potrzebuję czegoś, co mogę uruchomić na shellu, ponieważ nie dysponuję zbyt dobrym łączem, a do tego niektóre serwisy streamingowe mają nienajlepsze serwery, które przy wielu userach działają jeszcze gorzej, co w łącznym rezultacie powoduje, że ściągnięcie filmu w lepszej jakości czasem zajmuje kilka/kilkanaście godzin. Na shellu odpalam i później przynajmniej ściągam z szybkiego serwera. Ale pojemność mam ograniczoną do 5 GB, więc potrzebuję czegoś, co ściągnie i przekonwertuje video do 720p (tyle do oglądania mi wystarczy).

Wklejone przeze mnie polecenie ffmpeg dokładnie to robi, tj konwersja w locie. Pobiera, konwertuje i zapisuje do pliku. Wszystko na shellu, no chyba że nie masz tam ffmpeg to musisz doinstalować, powinno się dać bez roota.

No fakt :slight_smile:

Troszkę źle sformułowałem pytanie. Chodzi o to, że chcę takie ściąganie z konwersją odpalić na koncie shell, które ma pojemność 5 GB. Często natomiast potrzebuję ściągnąć kilkugodzinne video, które ma kilkanaście GB. Dlatego zastanawia mnie, czy to polecenie, żeby dokonać konwersji, musi najpierw dokonać ściągnięcia całego pliku video.

Polecenie ffmpeg które podałem zapisuje na dysk tylko plik po konwersji. Jednym słowem dane kompresowane są w locie bez żadnego pośredniego pliku. Jeżeli materiał ma 12GB ale dobierzesz parametry kompresji/rozdzielczość tak aby plik wynikowy dał około 3GB, to zapisany zostanie tylko ten plik 3GB.

@Bradlee, pozwolę sobie zadać jeszcze 2 pytania:

  1. W podanym przez Ciebie przykładzie użyłeś parametru: scale=1280:720. Czy można podać tylko wysokość, aby szerokość była proporcjonalna względem źródła?

  2. Czy da się jakoś obliczyć, jaką wartość parametrów preset oraz crf dobrać, przy rozdzielczości 720p, aby otrzymać plik wynikowy o określonej wielkości?

Skalowanie proporcjonalne uzyskasz z podając -1 jako jeden z wymiarów. Zobacz Scaling – FFmpeg → Keeping the Aspect Ratio. Niestety to nie zawsze zadziała, np gdy szerokość względem wysokości da w przeliczeniu jakiś ułamek, to ffmpeg zwróci błąd i wtedy musisz podać oba wymiary.

Dobre pytanie, chyba trzeba metodą prób i błędów, podobna dyskusja toczy się tutaj filesize - How to calculate ffmpeg output file size? - Stack Overflow