0

I am trying to know the duration of a distant video file (say mp4).

I know already how to get the duration of a local video file:

import xml.etree.ElementTree as eltt, subprocess as spr

def size_from_fn(file_name):
    size = eltt.fromstring(
        spr.run(["ffprobe",
            "-i", file_name,
            "-show_format", "-output_format", "xml"
            ], stdout = spr.PIPE, stderr = spr.STDOUT).stdout.decode()
        ).find("format").get("duration")
    return size

def size_from_fd(file_descriptor):
    size = eltt.fromstring(
        spr.run(["ffprobe",
            "-i", "pipe:0",
            "-show_format", "-output_format", "xml"
            ], stdin = file_descriptor, stdout = spr.PIPE, stderr = spr.STDOUT).stdout.decode()
        ).find("format").get("duration")
    return size

def size_from_data(file_name):
    size = eltt.fromstring(
        spr.run(["ffprobe",
            "-i", "pipe:0",
            "-show_format", "-output_format", "xml"
            ], input = data, stdout = spr.PIPE, stderr = spr.STDOUT).stdout.decode()
        ).find("format").get("duration")
    return size

All work perfectly

Also I know how to get an HTTP request as a file descriptor:

import requests as rq

def url_to_fd(url):
    req = rq.get(url, stream = True)
    return req.raw

It also works

However the combination of the two fails with the message from ffprobe : Invalid data found when processing input

I have no idea why, I just know the returned file descriptor from URL has the difference of not being seekable (one-way reading) but by replacing this method of a normal file descriptor:

with open("test.mp4", "rb") as f:
    f.seek = None
    size_of_fd(f)

this works and thus shows that ffprobe doesn't use any seeking

Also doing this works so I don't know what is up:

def get_duration(url):
    complete_data = url_to_fd(url).read()
    return size_of_data(complete_data)

My problem is that video files may be arbitrarily large so I can't afford to download the whole video.

Test video URL

3
  • Wow all this hassle for nothing. I have been trying to figure this out for hours ! Commented Apr 26 at 14:36
  • maybe you use url for page with HTML instead of url to raw data with video. maybe first check what you really get in req.raw - if you see some HTML then it is wrong URL. Commented Apr 26 at 14:56
  • BTW: to get directly duration you can add -v quiet -show_entries format=duration -output_format default=noprint_wrappers=1:nokey=1 , ffmpeg - How to get video duration in seconds? - Super User Commented Apr 26 at 15:36

1 Answer 1

1

As @tepalia already mentioned you can use URL directly in ffprobe

I only add that you can also add other parameteres to get directly duration

ffprobe https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4  \
-v quiet \
-show_entries format=duration \
-output_format default=noprint_wrappers=1:nokey=1

Result:

596.474195

-v quiet - removes information about program, libraries, etc.

-show_entries format=duration - shows only duration as [FORMAT]duration=596.474195[/FORMAT]

-output_format default=noprint_wrappers=1:nokey=1 - removes wrapper [FORMAT][/FORMAT] and key duration=


If you need other values at the same time (ie. size) then you can use format=duration,size and every value will be in separate line

596.474195
158008374

There is also -hide_banner similar to -v quiet which hides only part of information.
(-v means -verbose and it works also with other values - ie -v debug)


You can find more information on similar portal SuperUser or VideoProduction

For example: ffmpeg - How to get video duration in seconds? - Super User


Ther is also ffprobe Documentation

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.