ffmpeg - How to pass http headers?

44,327

Solution 1

Short Answer

Make sure you're using the latest ffmpeg, and use the -user-agent option.

Longer Answer

For debugging, I setup a BaseHTTPSever running at 127.0.0.1:8080 with do_GET() as:

def do_GET(self):
   try:
       f = open(curdir + sep + self.path, 'rb')
       self.send_response(200)
       self.end_headers()
       print("GET: "+ str(self.headers))
       self.wfile.write(f.read())
       f.close()
       return

   except IOError:
       self.send_error(404,'File Not Found: %s' % self.path)

With that running, this enabled me to run your command like:

ffmpeg  \
    -y \
    -timeout 5000000 \
    -map 0:0 \
    -an \
    -sn \
    -f md5 - \
    -headers "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36" \
    -headers "X-Forwarded-For: 13.14.15.66" \
    -i "http://127.0.0.1:8080/some_video_file.mp4" \
    -v trace

When I do this, I see the following relevant output from ffmpeg:

Reading option '-headers' ... matched as AVOption 'headers' with argument 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36'.
Reading option '-headers' ... matched as AVOption 'headers' with argument 'X-Forwarded-For: 13.14.15.66'.

On the server, I saw:

User-Agent: Lavf/56.40.101
X-Forwarded-For: 13.14.15.66

So it looks like ffmpeg is setting it's own. But there is an option -user-agent to ffmpeg, and when I replaced -headers "User-Agent: <foo>" with -user-agent "<foo>", I then did see it too on the server, alongside the X-Forwarded-For header:

User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36

Last note. There are lots of discussions around headers bugs in trac for ffmpeg. What I have observed above (that essentially it is working, perhaps with a small command change) was with a fairly recent version:

ffmpeg version 2.8.1 Copyright (c) 2000-2015 the FFmpeg developers
built with gcc 4.8 (Ubuntu 4.8.4-2ubuntu1~14.04)
configuration: --enable-libx264 --enable-gpl --prefix=/usr/local --enable-shared --cc='gcc -fPIC'
libavutil      54. 31.100 / 54. 31.100
libavcodec     56. 60.100 / 56. 60.100
libavformat    56. 40.101 / 56. 40.101
libavdevice    56.  4.100 / 56.  4.100
libavfilter     5. 40.101 /  5. 40.101
libswscale      3.  1.101 /  3.  1.101
libswresample   1.  2.101 /  1.  2.101
libpostproc    53.  3.100 / 53.  3.100

So, your next move might be make sure you have the latest version of ffmpeg.

Solution 2

Well, ffmpeg manual says to split multiple http-headers by CRLF. The problem is that you overwrite your first "-header" argument with the second "-header" as there can be only one "-header" argument.

For your example, you need to join User-Agent and X-Forwarded into one argument by valid CRLF like this:

-header "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36"$'\r\n'"X-Forwarded-For: 13.14.15.66"$'\r\n'

Solution 3

For set x:1 and y:2 for header ffmpeg request, use this:

ffmpeg -headers $'x:1\r\ny:2\r\n' -i 'http://sample.com' -y 'sample.mp4' -v debug

Result:

[http @ 0x358be00] Setting default whitelist 'http,https,tls,rtp,tcp,udp,crypto,httpproxy'
[http @ 0x358be00] request: GET / HTTP/1.1
User-Agent: Lavf/57.76.100
Accept: */*
Range: bytes=0-
Connection: close
Host: example.com
Icy-MetaData: 1
x:1
y:2
Share:
44,327

Related videos on Youtube

Lizozom
Author by

Lizozom

Updated on January 18, 2020

Comments

  • Lizozom
    Lizozom over 4 years

    I need to pass http headers (user agent and ip) to an ffmpeg command.

    I use the following command:

    ffmpeg  -y -timeout 5000000 -map 0:0 -an -sn -f md5 - -headers "User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.80 Safari/537.36" -headers "X-Forwarded-For: 13.14.15.66"  -i "http://127.0.0.1" 
    

    And I run a local node.js server to see the headers I get:

    'use strict';
    
    var express = require('express');
    
    var server = express();
    
    server.all('/*', function(req, res) {
      console.log(JSON.stringify(req.headers));
      res.sendFile('SampleVideo_1080x720_1mb.mp4', {root: '.'});
    
    });
    
    
    server.listen(80);
    

    I keep getting an error saying "No trailing CRLF found in HTTP header." and the request is stuck.

    If I drop the headers - everything works normally.

    I also tried putting both headers in one string, but any line breaking character I used (\r\n, \r\n, etc.) didn't work.

    Can someone help me figure out how to write this command correctly with the headers included?

    • Jameson
      Jameson over 8 years
      Just curious: did you also try using two separate -headers "<foo>\r\n" options, each with their own \r\n at the end of the option argument strings?
    • Lizozom
      Lizozom over 8 years
      Yes. It didn't work. I think I tried the full matrix of duplicating slashes, joining headers, etc.
    • Jameson
      Jameson over 8 years
      What specifically is the issue you are seeing with sending them? What does the receiver get?
    • Lizozom
      Lizozom over 8 years
      Actually I just set up a small local server to test - and it seems I am never able to send any headers what so ever (even if it is just one header)
    • Lizozom
      Lizozom over 8 years
      My goal is just to calculate the md5 of a video file, so this is pretty much what I need from this command. I ran trace like you did, but I don't see my headers being sent on the request.
    • shellter
      shellter over 8 years
      can't you use the md5 program? Good luck.
    • Lizozom
      Lizozom over 8 years
      @shellter - my code obviously does more than just an md5 calculation. This is just the first command in the flow.
    • shellter
      shellter over 8 years
      you wrote "My goal is just to calculate the md5 of a video file". Good luck.
    • arturn
      arturn over 2 years
      Just one more question... Is there any way to remove some of the defaults headers? For example, by default, it adds a 'Range: bytes=0-' header, but it's generating me a '406 Not acceptable' response.
  • Jameson
    Jameson over 8 years
    @shellter awesome glad it helps!
  • Lizozom
    Lizozom over 8 years
    @Jameson, the user agent worked for me, but when i'm trying to set up the ip - I'm still getting the "No trailing CRLF found in HTTP header." error
  • Lizozom
    Lizozom over 8 years
    Upgrading the ffmpeg version solved the second issue. I'm accepting the answer.
  • Jameson
    Jameson over 8 years
    @Lizozom awesome, glad we got it!
  • kampsj
    kampsj over 8 years
    Here is example commands for any HTTP header. jokecamp.com/blog/passing-http-headers-to-ffmpeg
  • Luca Steeb
    Luca Steeb about 7 years
    In a new version ffmpeg says that user-agent ist deprecated and user_agent should be used instead.
  • cirrus
    cirrus almost 4 years
    It seems the order is also important. If you put -i before -headers they'll be ignored. -headers first works well.
  • Fthr
    Fthr over 3 years
    for user agent u need to use -user_agent options to make it work precisely