2010-05-21 9 views
17

Necesito convertir videos para usar tanto en un reproductor flash como en el iPhone/iPod touch. Estoy usando la siguiente secuencia de comandos por lotes con ffmpeg:Uso de FFMPEG para convertir de manera confiable videos a mp4 para reproductores de iphone/ipod y flash

@echo off 
ffmpeg.exe -i %1 -s qvga -acodec libfaac -ar 22050 -ab 128k -vcodec libx264 -threads 0 -f ipod %2 

Esto siempre da salida a un archivo MP4, y siempre puedo jugar en mi PC. Los videos también parecen funcionar bien en mi iPhone 3GS. Pero con algunos archivos de entrada no funcionará para versiones anteriores de iPhone (3G y iPod touch).

Aquí está la salida de un ffmpeg tal archivo:

D:\ffmpeg>encode.bat d:\temp\recording.flv d:\temp\out.m4v 
FFmpeg version SVN-r18709, Copyright (c) 2000-2009 Fabrice Bellard, et al. 
    configuration: --enable-memalign-hack --prefix=/mingw --cross-prefix=i686-ming 
w32- --cc=ccache-i686-mingw32-gcc --target-os=mingw32 --arch=i686 --cpu=i686 --e 
nable-avisynth --enable-gpl --enable-zlib --enable-bzlib --enable-libgsm --enabl 
e-libfaac --enable-libfaad --enable-pthreads --enable-libvorbis --enable-libtheo 
ra --enable-libspeex --enable-libmp3lame --enable-libopenjpeg --enable-libxvid - 
-enable-libschroedinger --enable-libx264 
    libavutil  50. 3. 0/50. 3. 0 
    libavcodec 52.27. 0/52.27. 0 
    libavformat 52.32. 0/52.32. 0 
    libavdevice 52. 2. 0/52. 2. 0 
    libswscale  0. 7. 1/0. 7. 1 
    built on Apr 28 2009 04:04:42, gcc: 4.2.4 
[flv @ 0x187d650]skipping flv packet: type 18, size 164, flags 0 
Input #0, flv, from 'd:\temp\recording.flv': 
    Duration: 00:00:07.17, start: 0.001000, bitrate: N/A 
    Stream #0.0: Video: flv, yuv420p, 320x240, 1k tbr, 1k tbn, 1k tbc 
    Stream #0.1: Audio: nellymoser, 44100 Hz, mono, s16 
[libx264 @ 0x13518b0]using cpu capabilities: MMX2 SSE2Fast SSSE3 FastShuffle SSE 
4.2 
[libx264 @ 0x13518b0]profile Baseline, level 4.2 
Output #0, ipod, to 'd:\temp\out.m4v': 
    Stream #0.0: Video: libx264, yuv420p, 320x240, q=2-31, 200 kb/s, 1k tbn, 1k 
tbc 
    Stream #0.1: Audio: libfaac, 22050 Hz, mono, s16, 128 kb/s 
Stream mapping: 
    Stream #0.0 -> #0.0 
    Stream #0.1 -> #0.1 
Press [q] to stop encoding 
frame= 90 fps= 0 q=-1.0 Lsize=  128kB time=6.87 bitrate= 152.4kbits/s 
video:92kB audio:32kB global headers:1kB muxing overhead 2.620892% 
[libx264 @ 0x13518b0]slice I:8  Avg QP:29.62 size: 7047 
[libx264 @ 0x13518b0]slice P:82 Avg QP:30.83 size: 467 
[libx264 @ 0x13518b0]mb I I16..4: 17.9% 0.0% 82.1% 
[libx264 @ 0x13518b0]mb P I16..4: 0.6% 0.0% 0.0% P16..4: 23.1% 0.0% 0.0% 
0.0% 0.0% skip:76.3% 
[libx264 @ 0x13518b0]final ratefactor: 57.50 
[libx264 @ 0x13518b0]SSIM Mean Y:0.9544735 
[libx264 @ 0x13518b0]kb/s:8412.6 

Mi sospecha es que tiene algo que ver con la codificación de audio. Si es así, ¿alguien sabe cómo forzarlo a volver a codificar el audio en el formato correcto?

¿Alguna otra idea?

Respuesta

3

Creo que el problema es que el nivel H.264 es el nivel 4.2.

Algunos dispositivos Apple solo admiten hasta 3.0.

Aquí está la configuración de FFMPEG que suelen utilizar:

ffmpeg -i YOUR-INPUT.wmv -s qvga -b 384k -vcodec libx264 -r 23.976 -acodec libfaac -ac 2 -ar 44100 -ab 64k -vpre baseline -crf 22 -deinterlace -o YOUR-OUTPUT.MP4 

Se puede ajustar la velocidad, el tamaño y la tasa de bits, según sea necesario. Las configuraciones importantes están en el parámetro de configuración de la línea de base.

+0

Cuando intento esto, FFMPEG me dice que "[libx264 @ 0x7f85e8845400] perfil alto, nivel 1.3" ¿Cómo puedo solucionar este problema? – mxg

+9

¿qué/dónde está el archivo de configuración de línea de base? – badbod99

+0

estas son probablemente las configuraciones de línea de base a las que se hace referencia en la respuesta https://github.com/FFmpeg/FFmpeg/tree/master/presets – mulllhausen

2

Los ajustes mencionados ffmpeg no funcionó para mí (que no parecen tener el preset "de referencia" en la lista), los ajustes de ffmpeg que no hacen referencia a la línea de base, he publicado aquí: iPhone "cannot play" .mp4 H.264 video file

Spoiler :

 
ffmpeg -i INPUT -s 320x240 -r 30000/1001 -b 200k -bt 240k -vcodec libx264 -coder 0 -bf 0 -refs 1 -flags2 -wpred-dct8x8 -level 30 -maxrate 10M -bufsize 10M -acodec libfaac -ac 2 -ar 48000 -ab 192k OUTPUT.mp4 

la referencia oficial de Apple sobre el tema: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/CreatingVideoforSafarioniPhone/CreatingVideoforSafarioniPhone.html

2

Trate this python script.

Lo escribí yo mismo. Quizás lo encuentres útil también. Convierte archivos a mp4.

Debido a SO reglas aquí el código fuente completo:

#!/usr/bin/python 

# Copyright (C) 2007-2010 CDuke 
# This program is free software. You may distribute it under the terms of 
# the GNU General Public License as published by the Free Software 
# Foundation, version 2. 
# 
# This program is distributed in the hope that it will be useful, but 

# WITHOUT ANY WARRANTY; without even the implied warranty of 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General 
# Public License for more details. 
# 
# This program converts video files to mp4, suitable to be played on an iPod 
# or an iPhone. It is careful about maintaining the proper aspect ratio. 

from __future__ import division 
from datetime import datetime 
import sys 
import argparse 
import os 
import re 
import shlex 
import time 
from subprocess import Popen, PIPE 

DEFAULT_ARGS = '-f mp4 -y -vcodec libxvid -maxrate 1000k -mbd 2 -qmin 3 -qmax 5 -g 300 -bf 0 -acodec libfaac -ac 2 -flags +mv4 -trellis 2 -cmp 2 -subcmp 2' 
#DEFAULT_ARGS = '-f mp4 -y -vcodec mpeg4 -vtag xvid -maxrate 1000k -mbd 2 -qmin 3 -qmax 5 -g 300 -bf 0 -acodec libfaac -ac 2 -r 30000/1001 -flags +mv4 -trellis 2 -cmp 2 -subcmp 2' 
#DEFAULT_ARGS = '-y -f mp4 -vcodec libxvid -acodec libfaac' 
DEFAULT_BUFSIZE = '4096k' 
DEFAULT_AUDIO_BITRATE = '128k' 
DEFAULT_VIDEO_BITRATE = '400k' 
FFMPEG = '/usr/bin/ffmpeg' 

class device: 
    '''Describe properties of device''' 
    def __init__(self, name, width, height): 
     self.name = name 
     self.width = width 
     self.height = height 

class videoFileInfo: 
    def __init__(self, width, height, duration): 
     self.width = width 
     self.height = height 
     self.duration = duration 

devices = [device('ipod', 320, 240), device('iphone', 480, 320), 
device('desire', 800, 480)] 

def getOutputFileName(inputFileName, outDir): 
    if outDir == None: 
     outFileName = os.path.splitext(inputFileName)[0] + '.mp4' 
    else: 
     outFileName = os.path.join(outDir, os.path.basename(inputFileName)) 
    return outFileName 

def getVideoFileInfo(fileName): 
    p = Popen([FFMPEG, '-i', fileName], stdout = PIPE, stderr = PIPE) 
    fileInfo = p.communicate()[1] 
    videoRes = re.search(b'Video:.+ (\d+)x(\d+)', fileInfo) 
    w = float(videoRes.group(1)) 
    h = float(videoRes.group(2)) 
    duratMatch = re.search(b'Duration:\s+(\d+):(\d+):(\d+)\.(\d+)', fileInfo) 
    duration = float(duratMatch.group(1)) * 3600 
    duration += float(duratMatch.group(2)) * 60 
    duration += float(duratMatch.group(3)) 
    duration += float(duratMatch.group(4))/10 
    fileInfo = videoFileInfo(w, h, duration) 
    return fileInfo 

def getArguments(width, height, aspect): 
    args = {} 
    w = width 
    h = w // aspect 
    h -= (h % 2) 
    if h <= height: 
     pad = (height - h) // 2 
     pad -= (pad % 2) 
     pady = pad 
     padx = 0 
    else: 
     # recalculate using the height as the baseline rather than the width 
     h = height 
     w = int(h * aspect) 
     width -= (width % 2) 
     pad = (width - w) // 2 
     pad -= (pad % 2) 
     padx = pad 
     pady = 0 

    args['width'] = w 
    args['height'] = h 
    args['padx'] = padx 
    args['pady'] = pady 
    return args 

def getProgressBar(perc): 
    convInfo = 'Converted: [{}] {:.2%} \r' 
    num_hashes = round(perc * 100 // 2) 
    bar = '=' * num_hashes + ' ' * (50 - num_hashes) 
    return convInfo.format(bar, perc) 

def convert(inputFileName, outputFileName, args, audioBitrate, videoBitrate, devWidth, devHeight, aspect, duration): 
    cmd = '{ffmpeg} -i {inFile} {defaultArgs} -bufsize {bufsize} -s {width}x{height} -vf "pad={devWidth}:{devHeight}:{padx}:{pady},aspect={aspect}" -ab {audioBitrate} -b {videoBitrate} {outFile}'.format(ffmpeg=FFMPEG, inFile=inputFileName, defaultArgs=DEFAULT_ARGS, bufsize=DEFAULT_BUFSIZE, devWidth=devWidth, devHeight=devHeight, padx=args['padx'], pady=args['pady'], width=args['width'], height=args['height'], aspect=aspect, audioBitrate=audioBitrate, videoBitrate=videoBitrate, outFile=outputFileName) 
# cmd = '{ffmpeg} -i {inFile} {defaultArgs} -bufsize {bufsize} -s {width}x{height} -ab {audioBitrate} -b {videoBitrate} {outFile}'.format(ffmpeg=FFMPEG, inFile=inputFileName, defaultArgs=DEFAULT_ARGS, bufsize=DEFAULT_BUFSIZE, width=args['width'], height=args['height'], audioBitrate=audioBitrate, videoBitrate=videoBitrate, outFile=outputFileName) 
    print(cmd) 
    print() 
    start = datetime.today() 
    print('Converting started at ' + str(start)) 
    conv = Popen(shlex.split(cmd), shell=False, stdout=PIPE, stderr=PIPE) 
    while conv.poll() is None: 
     out = os.read(conv.stderr.fileno(), 2048) 
     last = out.splitlines()[-1] 
     timeMatch = re.search(b'time=([^\s]+)', last) 
     if timeMatch: 
      timeDone = float(timeMatch.group(1)) 
      perc = timeDone/duration 
      if sys.version_info > (3, 0): 
       exec("print(getProgressBar(perc), end='')") 
      else: 
       exec("print getProgressBar(perc),") 
      sys.stdout.flush() 
#  else: 
#   print(out) 
     time.sleep(0.5) 
    print(getProgressBar(1)) 
    end = datetime.today() 
    print('Converting ended at ' + str(end)) 
    print('Spended time: ' + str(end - start)) 

class mp4Converter(argparse.Action): 
    def __call__(self, parser, namespace, values, option_string = None): 
     outdir = namespace.outdir 
     for f in values: 
      outFileName = getOutputFileName(f.name, outdir) 
      fileInfo = getVideoFileInfo(f.name) 
      aspect = fileInfo.width/fileInfo.height 
      dev = next(d for d in devices if d.name == namespace.device) 
      args = getArguments(dev.width, dev.height, aspect) 
      convert(f.name, outFileName, args, namespace.AUDIO_BITRATE, namespace.VIDEO_BITRATE, dev.width, dev.height, aspect, fileInfo.duration) 
      print('file "{0}" converted successful'.format(f.name)) 

opts = argparse.ArgumentParser(
    description = 'Converter to MP4', 
    epilog = 'made by CDuke 2010') 
opts.add_argument('-V','--version', 
        action = 'version', 
        version = '0.0.1') 
opts.add_argument('-v', '--verbose', 
        action = 'store_true', 
        default = False, 
        help = 'verbose') 
opts.add_argument('-a', '--audio', 
        dest = 'AUDIO_BITRATE', 
        default = DEFAULT_AUDIO_BITRATE, 
        help = 'override default audio bitrate {0}'.format(DEFAULT_AUDIO_BITRATE)) 
opts.add_argument('-b', '--video', 
        dest = 'VIDEO_BITRATE', 
        default = DEFAULT_VIDEO_BITRATE, 
        help = 'override default video bitrate {0}'.format(DEFAULT_VIDEO_BITRATE)) 
opts.add_argument('-d', '--device', 
        choices = [d.name for d in devices], 
        default = 'ipod', 
        help = 'device that will play video') 
opts.add_argument('-o', '--outdir', 
        help = 'write files to given directory') 
opts.add_argument('file', 
        nargs = '+', 
        type = argparse.FileType('r'), 
        action = mp4Converter, 
        help = 'file that will be converted') 

opts.parse_args() 
1

El ffmpeg wiki proporciona alguna utilidad para la orientación actualizada sobre cómo codificar H.264 para dispositivos particulares. He aquí un extracto:

iOS Compatability ([​source][2]) 
Profile Level Devices              Options 
Baseline 3.0 All devices             -profile:v baseline -level 3.0 
Baseline 3.1 iPhone 3G and later, iPod touch 2nd generation and later  -profile:v baseline -level 3.1 
Main  3.1 iPad (all vers), Apple TV 2 and later, iPhone 4 and later -profile:v main -level 3.1 
Main  4.0 Apple TV 3 and later, iPad 2 and later, iPhone 4s and later -profile:v main -level 4.0 
High  4.0 Apple TV 3 and later, iPad 2 and later, iPhone 4s and later -profile:v high -level 4.0 
High  4.1 iPad 2 and later, iPhone 4s and later, iPhone 5c and later -profile:v high -level 4.1 
High  4.2 iPad Air and later, iPhone 5s and later      -profile:v high -level 4.2 
+0

Si bien este enlace puede responder a la pregunta, es mejor incluir las partes esenciales de la respuesta aquí y proporcionar el enlace de referencia. Las respuestas de solo enlace pueden dejar de ser válidas si la página vinculada cambia. – brezanac

+0

Acabo de agregar la tabla. Es complicado ya que algunas de las respuestas anteriores están desactualizadas, pero acepto que es útil tener la información en la respuesta. De esta manera, está el enlace wiki y una copia en línea por si acaso. – Pierz

0
ffmpeg -i test.mov -profile:v baseline -level 3.0 test.mp4 

Esto desactiva algunas funciones pero ofrece una mayor compatibilidad.

nuevo, aquí hay algunas etiquetas opcionales útiles para añadir para trabajar con la calidad y tamaño de archivo:

-preset: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo 

-crf: 0-51 

(modifica preestablecidos cuánto tiempo se necesita para comprimir el vídeo, con cada vez más rápido un tamaño de archivo más grande, y más lento obteniendo un tamaño de archivo más pequeño, mientras que crf modifica la calidad del video, con mayor calidad teniendo un tamaño de archivo más grande y baja calidad con un tamaño de archivo más pequeño.)

Cuestiones relacionadas