Estou tentando saber a duração de um arquivo de vídeo distante (digamos mp4).
Eu já sei como obter a duração de um arquivo de vídeo local :
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
Tudo funciona perfeitamente
Também sei como obter uma solicitação HTTP como um descritor de arquivo:
import requests as rq
def url_to_fd(url):
req = rq.get(url, stream = True)
return req.raw
Também funciona
Entretanto a combinação dos dois falha com a mensagem de ffprobe
:Invalid data found when processing input
Não tenho ideia do porquê, só sei que o descritor de arquivo retornado da URL tem a diferença de não ser pesquisável (leitura unidirecional), mas substitui este método de um descritor de arquivo normal:
with open("test.mp4", "rb") as f:
f.seek = None
size_of_fd(f)
isso funciona e assim mostra que ffprobe
não usa nenhuma busca
Isso também funciona, então não sei o que está acontecendo:
def get_duration(url):
complete_data = url_to_fd(url).read()
return size_of_data(complete_data)
Meu problema é que os arquivos de vídeo podem ser arbitrariamente grandes, então não posso me dar ao luxo de baixar o vídeo inteiro.
Como @tepalia já mencionou você pode usar
URL
diretamente emffprobe
Só acrescento que você também pode adicionar outros parâmetros para obter a duração diretamente
Resultado:
-v quiet
- remove informações sobre programas, bibliotecas, etc.-show_entries format=duration
- mostra apenas a duração como[FORMAT]duration=596.474195[/FORMAT]
-output_format default=noprint_wrappers=1:nokey=1
- remove o wrapper[FORMAT][/FORMAT]
e a chaveduration=
Se você precisar de outros valores ao mesmo tempo (por exemplo
size
), você pode usarformat=duration,size
e cada valor estará em uma linha separadaHá também
-hide_banner
algo semelhante-v quiet
que oculta apenas parte da informação.(
-v
significa-verbose
e funciona também com outros valores - ou seja-v debug
)Você pode encontrar mais informações no portal similar SuperUser ou VideoProduction
Por exemplo: ffmpeg - Como obter a duração do vídeo em segundos? - Superusuário
Há também a documentação do ffprobe