jueves, 23 de abril de 2009

Convertir vídeo AVCHD a hd-mov para cinelerra.




Este tutorial describe como codificar vídeo en formato AVCHD (.mts, m2ts, etc.) a QuickTimeLinux de alta definición.

El tutorial está publicado en el wiki de www.aulir.com aquí

Aunque he realizado algunas modificaciones que simplifican el script y lo hacen más legible.

Aquí teneis el script.
Espero que os sirva...

#!/bin/sh

# Extraemos el nombre del script ejecutable
NOMBRE=$0

# Buscamos el ejecutable de ffmpeg
#FFMPEG=ffmpeg
FFMPEG=`which ffmpeg`

# Elegimos la extensión de salida
format=mov

# Ratio de entrada y salida
irate=25000/1001 # input
orate=25000/1001 # output

# Cámara que se ha utilizado
CAMARA=CANON

# Preset elegido por defecto
PRESET=edit # as below

while :
do
case "$1" in
-d)
set -x
;;

-c)
shift
CAMARA=$1
shift
;;

-p)
shift
PRESET=$1
shift
;;

-i)
shift
isize=$1
shift
;;

-x)
shift
PUT_HERE=true
;;

-f)
shift
format=$1
shift
;;

*)
break
;;
esac
done

# Archivo de entrada
input=$1

######################################
# Tipos de tamaño de vídeo, auido, etc.
MACRO_SIZE_HUGE=1920x1080
MACRO_SIZE_LARGE=1366x768
MACRO_SIZE_MEDIUM=1280x720
MACRO_SIZE_SMALL=640x360
MACRO_SIZE_THUMB=320x180

#MACRO_VIDEO_MJPEG="-vcodec mjpeg -sameq -shortest -f $format"
#MACRO_VIDEO_MPEG4="-vcodec mpeg4 -sameq -shortest -f $format"
MACRO_VIDEO_MJPEG="-vcodec mjpeg -sameq -f $format"
MACRO_VIDEO_MPEG4="-vcodec mpeg4 -sameq -f $format"
MACRO_VIDEO_VC3="-vcodec dnxhd -b 90Mb -f $format -an"

MACRO_AUDIO_AAC="-acodec libfaac -ac 2 -ab 128k -ar 44100"
MACRO_AUDIO_AAC_HD="-acodec libfaac -ac 2 -ab 448k -ar 48000"
MACRO_AUDIO_THUMB="-acodec libfaac -ac 1 -ab 64k -ar 22050"

MACRO_AUDIO_RAW="-acodec pcm_s16le -ac 2 -ar 48000"
MACRO_AUDIO_COPY="-acodec copy"
######################################

# Corrector de sincronía entre audio y video en función del fabricante de la cámara
if [ "$CAMARA" = CANON ]; then
#correccion=2.5004190476 # CANON
#correccion=2.497591614 # CANON EN EL PORTATIL ASUS
correccion=2.498284520 # CANON EN EL ASUS 2
fi

if [ "$CAMARA" = SONY ]; then
correccion=2.083334442 # SONY
fi
irate2=`echo "$irate * $correccion" | bc`

# Si solo se introduce el nombre del ejecutable, se muestra una ayuda
if [ "x$1" = x ]
then
#------------------------------------------------------------------
cat 1>&2 <$NOMBRE luismanolo@gmail.com

Uso: $NOMBRE [opciones] archivo.mts ...

Opciones:
-d # activa el depurado
-p PRESET # establece el preset
-i SIZE # especifica el tamaño (default is 1920x1080)
-f FORMAT # especifica el formato de salida (default is mov)
-c CAMARA # fabricante de la cámara (SONY/CANON)

Presets:
vc3 # Codec equivalente al Apple ProRes
thumb # $MACRO_SIZE_THUMB mpeg4 + aac audio (primeros 20 segundos de video)
small # $MACRO_SIZE_SMALL mpeg4 + aac audio
medium # $MACRO_SIZE_MEDIUM mpeg4 + aac audio
large # $MACRO_SIZE_LARGE mpeg4 + aac audio
huge # $MACRO_SIZE_HUGE mpeg4 + aac audio
edit-mp4 # $MACRO_SIZE_MEDIUM mpeg4 keyframes + raw audio
edit-mj # $MACRO_SIZE_MEDIUM mjpeg + raw audio
edit # shorthand for 'edit-mj'

Ejemplos:

Convertir archivos AVCHD a 720p para editar con Cinelerra
$NOMBRE -p edit *.mts

Crear un video corto para previsualizar
$NOMBRE -p thumb *.mts

EOF
exit 1
fi
##################################################################

case $PRESET in

# am assuming editing is done at MEDIUM/720p
# with raw audio and best quality video

vc3)
osize=$MACRO_SIZE_HUGE
oaudio_in="$MACRO_AUDIO_RAW"
#oaudio_out="$MACRO_AUDIO_COPY"
oaudio_out="$MACRO_AUDIO_COPY_HD"
ovideo="$MACRO_VIDEO_VC3"
osuffix=vc3.$format
;;

edit|edit-mj)
osize=$MACRO_SIZE_MEDIUM
oaudio_in="$MACRO_AUDIO_RAW"
#oaudio_out="$MACRO_AUDIO_COPY"
oaudio_out="$MACRO_AUDIO_COPY_HD"
ovideo="$MACRO_VIDEO_MJPEG"
osuffix=edit-mj.$format # this one needed disambiguation
;;

edit-mp4)
osize=$MACRO_SIZE_MEDIUM
oaudio_in="$MACRO_AUDIO_RAW"
oaudio_out="$MACRO_AUDIO_COPY"
ovideo="$MACRO_VIDEO_MPEG4 -intra"
osuffix=$PRESET.$format
;;

# playback presets below

huge) # novelty, not meant for serious use
osize=$MACRO_SIZE_HUGE
oaudio_in="$MACRO_AUDIO_RAW"
oaudio_out="$MACRO_AUDIO_COPY"
ovideo="$MACRO_VIDEO_MPEG4"
osuffix=$PRESET.$format
;;

large)
osize=$MACRO_SIZE_LARGE
oaudio_in="$MACRO_AUDIO_RAW"
oaudio_out="$MACRO_AUDIO_AAC"
ovideo="$MACRO_VIDEO_MPEG4"
osuffix=$PRESET.$format
;;

medium)
osize=$MACRO_SIZE_MEDIUM
oaudio_in="$MACRO_AUDIO_RAW"
oaudio_out="$MACRO_AUDIO_AAC"
ovideo="$MACRO_VIDEO_MPEG4"
osuffix=$PRESET.$format
;;

small)
osize=$MACRO_SIZE_SMALL
oaudio_in="$MACRO_AUDIO_RAW"
oaudio_out="$MACRO_AUDIO_AAC"
ovideo="$MACRO_VIDEO_MPEG4"
osuffix=$PRESET.$format
;;

thumb)
osize=$MACRO_SIZE_THUMB
itruncate="-t 00:00:20" # only set here for thumbnails; 20s -> 10s
oaudio_in="$MACRO_AUDIO_RAW"
oaudio_out="$MACRO_AUDIO_THUMB"
ovideo="$MACRO_VIDEO_MPEG4"
osuffix=$PRESET.$format
;;

*)
echo $NAME: Preset desconocido $PRESET
exit 1
;;

esac #

##################################################################
# Filtramos los tipos de archivos permitidos
case $input in
*.MTS) ;;
*.mts) ;;
*.M2TS) ;;
*.m2ts) ;;
*) echo no se puede manejar el archivo $input ; continue ;;
esac

##################################################################

# salida
output=$input.$osuffix

# salida en el mismo directorio en el que se ejecuta el script
#output=`basename $output`

# Archivo de aviso
avisowav=.aviso.wav

# Set XAUDIO and XVIDEO filenames
XAUDIO=$input.wav # scratch file
XVIDEO=- # pipe

# detecta el tamaño
if [ -z $isize ]; then
isize=$($FFMPEG -i $input 2>&1 | sed -n "s/.* Video: h264, yuv420p, \([^ ]*\) .*/\1/p")
#ifps=$($FFMPEG -i $input 2>&1 | sed -n "s/.* Video: h264, yuv420p, \([^ ]*\) .*/\1/p")
fi

##################################################################
# Extraemos el audio
$FFMPEG -y $itruncate -i $input -vn $oaudio_in $XAUDIO

# Extraemos unos segundos de audio para avisar del final del codificado
$FFMPEG -y -t 00:00:07 -i $XAUDIO $avisowav

echo "------------------------------------------------------------------"

# Extraemos el video en crudo y lo mezclamos con el audio extraido
$FFMPEG -y $itruncate \
-i $input \
-an \
-pix_fmt yuv420p -f rawvideo $XVIDEO |
$FFMPEG -y \
-i $XAUDIO \
-r $irate2 -s $isize -pix_fmt yuv420p -f rawvideo -i $XVIDEO \
-r $orate -s $osize $ovideo \
$oaudio_out \
$output \
2>salida.txt

##################################################################
# Calculamos el desfase entre el audio y el vídeo
isize1=$($FFMPEG -i $output 2>&1 | sed -n "s/.* Duration: \([^ ]*\) .*/\1/p")
isize2=$($FFMPEG -i $XAUDIO 2>&1 | sed -n "s/.* Duration: \([^ ]*\) .*/\1/p")

horas1=$(echo $isize1 | cut -d ":" -f 1)
horas2=$(echo $isize2 | cut -d ":" -f 1)

minutos1=$(echo $isize1 | cut -d ":" -f 2)
minutos2=$(echo $isize2 | cut -d ":" -f 2)

segundos1=$(echo $isize1 | cut -d ":" -f 3 | cut -d "." -f 1)
segundos2=$(echo $isize2 | cut -d ":" -f 3 | cut -d "." -f 1)

decimas1=$(echo $isize1 | cut -d ":" -f 3 | cut -d "." -f 2 | cut -d "," -f 1)
decimas2=$(echo $isize2 | cut -d ":" -f 3 | cut -d "." -f 2 | cut -d "," -f 1)

totalsegundos1=`echo "( $horas1 * 3600 ) + ( $minutos1 * 60 ) + $segundos1" | bc`.$decimas1
totalsegundos2=`echo "( $horas2 * 3600 ) + ( $minutos2 * 60 ) + $segundos2" | bc`.$decimas2

relacion12=`echo "scale=9;$totalsegundos1 / $totalsegundos2" | bc`
recomendable=`echo "scale=9;0$relacion12 * $correccion" | bc`
echo "******************************************************"
echo "Corrección utilizada = "$correccion
echo " Tiempo de video "$totalsegundos1
echo " Tiempo de audio "$totalsegundos2
echo " Longitud video / Longitud audio = "$relacion12
echo "Corrección recomendable = "$recomendable
echo "******************************************************"

# avisamos del final del codificado
mplayer $avisowav

exit 0

2 comentarios:

  1. Hola,
    ffmpeg tiene una evolución muy rápida, por lo que es conveniente decir qué revisión exacta has usado (ffmpeg -v).
    Otra cosa que me llama la atención es que usas 25000/1001. Yo no tengo cámara HD, así que no conozco las costumbres de los fabricantes, pero de verdad usa CANON eso en lugar de los 25 fps exactos de PAL?
    Saludos,
    Víctor

    ResponderEliminar
  2. Pues lo del 25000/1001 no te puedo decir si es necesario, o no. Lo que sí es cierto es que en todos los scripts que he consultado, utilizan estos valores, y de momento me va bien.

    ResponderEliminar