2013-09-25 19:35:33 +0000 2013-09-25 19:35:33 +0000
75
75

Jak uzyskać czas trwania wideo w sekundach?

Jak mogę uzyskać czas trwania wideo w sekundach?

Co już próbowałem:

ffmpeg -i file.flv 2>&1 | grep "Duration"
  Duration: 00:39:43.08, start: 0.040000, bitrate: 386 kb/s

mediainfo file.flv | grep Duration
Duration : 39mn 43s

To co blisko, ale nie jest tak dokładne, 2383 to 39,71 minuty

ffmpeg -i file.flv 2>&1 | grep "Duration"| cut -d ' ' -f 4 | sed s/,// | sed 's@\..*@@g' | awk '{ split($1, A, ":"); split(A[3], B, "."); print 3600*A[1] + 60*A[2] + B[1] }'
2383
```.

Odpowiedzi (9)

105
105
105
2015-07-26 22:07:37 +0000

Po prostu użyj ffprobe bezpośrednio. Nie ma potrzeby używania sed, grep, itp. Istnieje kilka “czasów trwania”, które możesz uzyskać (w zależności od danych wejściowych).

Format (kontener) duration

$ ffprobe -v error -show_entries format=duration \
  -of default=noprint_wrappers=1:nokey=1 input.mp4

30.024000

Dodanie opcji -sexagesimal spowoduje użycie formatu jednostki czasu HOURS:MM:SS.MICROSECONDS:

0:00:30.024000

Czas trwania strumienia wideo

$ ffprobe -v error -select_streams v:0 -show_entries stream=duration \
  -of default=noprint_wrappers=1:nokey=1 input.mp4
30.000000

Powyższe komendy pochodzą z FFmpeg Wiki: FFprobe Tips .

Z ffmpeg

Możesz potrzebować całkowicie zdekodować dane wejściowe jeśli stwierdzisz brak kontenera lub czasu trwania strumienia lub niedokładność (prawdopodobnie z powodu uszkodzonego lub obciętego pliku).

$ ffmpeg -i input.mp4 -f null -
  …
  frame= 1587 fps=0.0 q=0.0 Lsize=N/A time=00:01:03.48 bitrate=N/A

W tym przykładzie time=00:01:03.48 jest czasem trwania:

To, jak długo to potrwa, zależy oczywiście od złożoności dekodowania i czasu trwania danych wejściowych oraz możliwości Twojego komputera.

35
35
35
2013-09-25 19:41:05 +0000

Aby otrzymać minuty, musisz podzielić 2383 sekundy przez 60.

39.7167

a następnie pomnożyć część ułamkową .7167 przez 60, aby otrzymać pozostałe sekundy.

43.002

Tak więc jest to 39 minut i 43 sekundy. Wygląda na to, że aplikacja podaje dokładną wartość.

34
34
34
2013-09-25 21:10:07 +0000

Jeśli masz ffmpeg, powinieneś mieć również ffprobe:

ffprobe -i input.file -show_format | grep duration
ffprobe -i input.file -show_format -v quiet | sed -n 's/duration=//p'

To również da ułamki sekund, jeśli jest to problem, możesz dalej przetwarzać to dalej za pomocą sed.

3
3
3
2018-05-05 08:00:38 +0000
mediainfo --Output='General;%Duration%' file.flv

Wypisuje czas trwania w milisekundach jako pojedynczą wartość całkowitą. Nie ma potrzeby stosowania grep/cut/sed/…

3
3
3
2013-09-25 19:56:50 +0000

Rozwiązanie z mplayer, który daje sekundy bezpośrednio:

mplayer -identify -frames 0 -vo null -nosound file.flv 2>&1 | awk -F= '/LENGTH/{print $2}'
3
3
3
2014-06-16 22:06:49 +0000

Dla mojego ffmpeg-0.6.5-1.el6.rf.x86_64, aby uzyskać tylko drugi, format polecenia ffprobe jest:

ffprobe <file> -show_format 2>&1 | sed -n 's/duration=//p'
0
0
0
2019-08-30 19:39:55 +0000

Jeśli potrzebujesz tylko zapytać o metadane:

ffprobe -hide_banner -v quiet -show_streams -print_format flat video.mp4

[…]

streams.stream.0.duration="5221.146009"

[…]

Więc możesz go sparsować:

while read -r; do
  if [["$REPLY" =~ ^streams\.stream\.([0-9])+\.duration=\"([^"]+)\"$ ]]; then
    echo -E Duration of stream "${BASH_REMATCH[1]}": "${BASH_REMATCH[2]}"
  fi
done < <(ffprobe -hide_banner -v quiet -show_streams -print_format flat video.mp4)

Ale jeśli chcesz uzyskać efektywny czas trwania kontenera, musisz go zdekodować:

AV_LOG_FORCE_NOCOLOR=y ffmpeg -nostdin -hide_banner -nostats -loglevel info -i video.mp4 -f null -c copy - 2>&1 | tail -n 2

Zdekodowanie go zajmie trochę czasu procesora, aż do:

[…]

frame=130527 fps=53271 q=-1.0 Lsize=N/A time=01:27:01.12 bitrate=N/A speed=2.13e+03x
video:152014kB audio:40790kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

Wtedy można go sparsować:

if [["$(AV_LOG_FORCE_NOCOLOR=y ffmpeg -nostdin -hide_banner -nostats -loglevel info -i video.mp4 -f null -c copy - 2>&1 | tail -n 2 | head -n 1)" =~ \ time=([0-9]+):([0-9]{2}):([0-9]{2})\.([0-9]+) ]]; then
  declare duration=0 us="${BASH_REMATCH[4]}" t
  for t in "${BASH_REMATCH[@]:1:3}"; do
    ((duration *= 60))
    ((duration += ${t#0} ))
  done
  while [${#us} -lt 6]; do us+=0; done
  ((us >= 500000)) && ((duration++))
  ((duration)) || ((duration++))
fi
echo -E Duration: "$duration"
```.
0
0
0
2017-06-01 01:01:24 +0000

Natknąłem się na problem uzyskania dziwnych i nieprawidłowych metadanych z niektórych plików wideo, z którymi pracowałem i nie mogłem znaleźć wzorca lub jakiegokolwiek rodzaju obsługi przy użyciu kodu i narzędzi takich jak ffmpeg, mp4box, ffprobe, mediainfo, mplayer, aby uzyskać prawdziwy czas trwania wideo.

Identyfikacja prawdziwego czasu trwania wideo była wymagana dla projektu, nad którym pracowałem i jedynym sposobem, jaki znalazłem, aby zawsze mieć rację, było ponowne kodowanie pliku wideo za pomocą ffmpeg i zmuszanie zakodowanych plików do ignorowania metadanych oryginalnego pliku, jak:

ffmpeg -i INPUT_FILENAME -acodec copy -vcodec copy -map_metadata -1 OUTPUT_FILENAME"

(To może działać szybciej niż się spodziewasz. Byłem zaskoczony, dla typu zawartości i środowiska, którego używałem, średni czas wynosił 2 sekundy)

… a następnie uzyskać czas trwania przy użyciu wybranego przez siebie narzędzia. Lubię mediainfo, btw: - “mediainfo FILE –Inform="Video;%Duration%” daje ci czas trwania w milisekundach.

-6
-6
-6
2015-04-27 01:59:24 +0000

Jeśli chcesz DOKŁADNY czas trwania, zapomnij o FFmpeg. Daje on tylko oszacowanie na podstawie rozmiaru plików i średniego bitrate. Znalazłem, w niektórych przypadkach, szacowany czas trwania jest przesunięty o 2x!

Na Linuksie, jeśli plik jest tworzony i modyfikowany tylko podczas wspomnianego nagrywania wideo, alternatywnym rozwiązaniem byłoby użycie czasu utworzenia i ostatniej modyfikacji do obliczenia czasu trwania, jak w:

stat -c "%X %Y" video.mpg | awk '{print $2 - $1}'