I try to encode audio to AAC with profile FF_PROFILE_AAC_LOW by the following settings.
oc_cxt->profile = FF_PROFILE_AAC_LOW;
Also from the output of av_dump_format, I got this
Metadata:
encoder : Lavf57.36.100
Stream #0:0: Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 192 kb/s
But the output is different. Everything is ok, except the output is AAC, not AAC (LC). By using ffprobe to detect, the output information is
$ ffprobe o.m4a
...
Stream #0:0(und): Audio: aac (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 195 kb/s (default)
...
AAC (LC) is the desired result I need.
But from the command line, ffmpeg can generate AAC (LC) output. Below is a small test.
$ ffmpeg -f lavfi -i aevalsrc="sin(440*2*PI*t):d=5" aevalsrc.m4a
$ ffprobe aevalsrc.m4a
...
Stream #0:0(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, mono, fltp, 69 kb/s (default)
...
How can I select FF_PROFILE_LOW to get AAC (LC) output?
This was caused by new ffmpeg api which I didn't notice.
The extra data need to copy back to AVStream->codecpar->extradata after avcodec_open2. After that, the ffprobe can detect output is the format I need, AAC (LC).
The following is a code snippet from ffmpeg.c
if (!ost->st->codecpar->extradata && avctx->extradata) {
ost->st->codecpar->extradata = av_malloc(avctx->extradata_size + FF_INPUT_BUFFER_PADDING_SIZE);
if (!ost->st->codecpar->extradata) {
av_log(NULL, AV_LOG_ERROR, "Could not allocate extradata buffer to copy parser data.\n");
exit_program(1);
}
ost->st->codecpar->extradata_size = avctx->extradata_size;
memcpy(ost->st->codecpar->extradata, avctx->extradata, avctx->extradata_size);
}
Hopefully it would be helpful to anyone use the latest version of ffmpeg (3.x).
Here, I actually wants to merge two strings out1 & out2 (which contains the first and second 30sec long video data) and write that to a file. So that I will get a 1min long playable video file. But what I am getting is the first 30sec video only. How should I edit this code to achieve that ? Please help me. Thanks a lot in advance.
import subprocess,os
ffmpeg_command1 = ["ffmpeg", "-i", "PATH/connect.webm", "-vcodec", "copy", "-ss", "00:00:00", "-t", "00:00:30","-f", "webm", "pipe:1"]
p1 = subprocess.Popen(ffmpeg_command1,stdout=subprocess.PIPE)
out1, err = p1.communicate()
ffmpeg_command2 = ["ffmpeg", "-i", "PATH/connect.webm","-vcodec", "copy", "-ss", "00:00:31", "-t", "00:00:30","-f", "webm", "pipe:1"]
p2 = subprocess.Popen(ffmpeg_command2,stdout=subprocess.PIPE)
out2, err1 = p2.communicate()
string = out1 + out2
fname = "PATH/final.webm"
fp = open(fname,'wb')
fp.write(string)
fp.close()
Please help me. I struck.
If you want to concat two videos with ffmpeg, it works like that:
ffmpeg -vcodec copy -isync -i \
"concat:file1.mp4|file2.mp4|...|fileN.mp4" \
outputfile.mp4
#coding=utf-8
import os
#Function to create a file list in the folder
import os
s = os.sep
path = r"F:\folder_mp4_files\temp"
def create_file_list(path):
return_list = []
for filenames in os.walk(path):
for file_list in filenames:
for file_name in file_list:
if file_name.endswith((".mp4")):
return_list.append(path+s+file_name)
return return_list
alist = create_file_list(path)
tsString = '|'.join([i.replace('.mp4','.ts') for i in alist])
print(tsString)
# mp4 converts to ts
for i in alist:
noExtension = i.replace('.mp4','')
# batch processing
os.system("ffmpeg -i %s -vcodec copy -acodec copy -vbsf h264_mp4toannexb %s.ts" % (i,noExtension))
# Remove used mp4 files
for i in alist:
os.remove(i)
os.system("""ffmpeg -i concat:"{0}" -acodec copy -vcodec copy -absf aac_adtstoasc {1}""".format(tsString, alist[0]))
# Remove used ts files
for i in alist:
os.remove(i.replace('.mp4','.ts'))
I need to convert videos for use in both a flash player and the iphone/ipod touch. I'm using the following batch script with ffmpeg:
#echo off
ffmpeg.exe -i %1 -s qvga -acodec libfaac -ar 22050 -ab 128k -vcodec libx264 -threads 0 -f ipod %2
This always outputs an mp4 file, and I can always play it on my PC. The videos also seem to play fine on my iphone 3GS. But with some input files it won't work for older iphone versions (3G and iPod touch).
Here's the ffmpeg output from one such file:
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
My suspicion is that it has something to do with the audio encoding. If so, does anyone know how to force it to reencode the audio to the proper format?
Any other ideas?
WARNING: this answer is 10 years old and reported not to work anymore.
I think the issue is the H.264 level being level 4.2.
Some of the Apple devices only support up to 3.0.
Here's the FFMPEG settings I usually use:
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
You can adjust the rate, size and bitrate as needed. The important settings are in the baseline config param.
The ffmpeg wiki provides some useful up to date guidance on how to encode H.264 for particular devices. Here's an excerpt from Apple's docs with corresponding profiles:
iOS Compatability
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
ffmpeg -i test.mov -profile:v baseline -level 3.0 test.mp4
This disables some features but offers greater compatibility.
Also, here are some useful optional tags to add for working with the quality and file size:
-preset: ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow, placebo
-crf: 0-51
(preset modifies how long it takes to compress your video, with faster getting a bigger file size, and slower getting a smaller file size, whereas crf modifies the video quality, with higher quality having a bigger file size, and lower quality having a smaller file size.)
The listed ffmpeg settings didn't work for me (I don't seem to have the "baseline" preset listed), ffmpeg settings that don't reference baseline, I posted over here: 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
The official Apple reference on the subject: http://developer.apple.com/library/safari/#documentation/AppleApplications/Reference/SafariWebContent/CreatingVideoforSafarioniPhone/CreatingVideoforSafarioniPhone.html
Try this python script.
I wrote it for myself. Maybe you will find it useful too. It converts files to mp4.
Because of SO rules here the complete source code:
#!/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()
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -profile:v main -crf 1 -preset medium -c:a aac -movflags +faststart output.mp4
ffmpeg.exe -i "Video.mp4" -vcodec libx264 -preset fast -profile:v baseline -lossless 1 -vf "scale=720:540,setsar=1,pad=720:540:0:0" -acodec aac -ac 2 -ar 22050 -ab 48k "Video (SD).mp4"
I had the same problem. I wanted to convert mainly videos for an iPod 5G. Every Info I found was either outdated or did not work for me.
So finally I stumbled upon some parameters that finally worked:
ffmpeg -i "INPUTFILE" \
-f mp4 -vcodec mpeg4 \
-vf scale=-2:320 \
-maxrate 1536k -b:v 768 -qmin 3 -qmax 5 -bufsize 4096k -g 300 \
-c:a aac -b:a 128k -ar 44100 -ac 2 \
"OUTPUTFILE.mp4"
Some remarks:
I let ffmpeg scale it to a height of 320, because for me this is the sweet spot. The files are not too big, and they also sync to an iPod Touch which has a Screen of 480x320, which then uses the full video. The Screen of the iPod is 320x240, so it could also be scaled to 240 height. The iPod seems support up to 480p, which is nice if you want to output the video to some other source.
The Audio quality can be changed if needed.
I did not try touching the other parameters as they work fine and produce decent results.
EDIT
I modified the command a tiny bit, as I had problems with some files which had audio tracks encoded in 48khz and more than 2 channels.
Got here because the simplest ffmpeg conversion approach was not producing an mp4 that would play on iOS for some reason.
Found settings that work for me in 2019 here:
https://gist.github.com/jaydenseric/220c785d6289bcfd7366
ffmpeg -i input.mov -c:v libx264 -pix_fmt yuv420p -profile:v baseline -level 3.0 -crf 22 -preset veryslow -vf scale=1280:-2 -c:a aac -strict experimental -movflags +faststart -threads 0 output.mp4
Im trying to automate video conversion with powershell and ffmpeg tool.
Ffmpeg have detailed output about video if called without all nessesary parameters. Usually it reports about error and display input file info if one specified.
Ex I interactively executed such command:
d:\video.Enc\ffmpeg.exe -i d:\video.Enc\1.wmv
this is powershell console output
ffmpeg.exe : FFmpeg version SVN-r20428, Copyright (c) 2000-2009 Fabrice Bellard, et al.
row:1 char:24
+ d:\video.Enc\ffmpeg.exe <<<< -i d:\video.Enc\1.wmv
+ CategoryInfo : NotSpecified: (FFmpeg version ...Bel
lard, et al.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
built on Nov 1 2009 04:03:50 with gcc 4.2.4
configuration: --enable-memalign-hack --prefix=/mingw --cross-pre
fix=i686-mingw32- --cc=ccache-i686-mingw32-gcc --target-os=mingw32
--arch=i686 --cpu=i686 --enable-avisynth --enable-gpl --enable-vers
ion3 --enable-zlib --enable-bzlib --enable-libgsm --enable-libfaad
--enable-pthreads --enable-libvorbis --enable-libtheora --enable-li
bspeex --enable-libmp3lame --enable-libopenjpeg --enable-libxvid --
enable-libschroedinger --enable-libx264 --enable-libopencore_amrwb
--enable-libopencore_amrnb
libavutil 50. 3. 0 / 50. 3. 0
libavcodec 52.37. 1 / 52.37. 1
libavformat 52.39. 2 / 52.39. 2
libavdevice 52. 2. 0 / 52. 2. 0
libswscale 0. 7. 1 / 0. 7. 1
[wmv3 # 0x144dc00]Extra data: 8 bits left, value: 0
Seems stream 1 codec frame rate differs from container frame rate:
1000.00 (1000/1) -> 15.00 (15/1)
Input #0, asf, from 'd:\video.Enc\1.wmv':
Duration: 00:12:0
2.00, start: 5.000000, bitrate: 197 kb/s
Stream #0.0(eng): Audio: wmav2, 44100 Hz, 1 channels, s16, 48 k
b/s
Stream #0.1(eng): Video: wmv3, yuv420p, 1024x768, 137 kb/s, 15 tbr, 1k tbn, 1k tbc Metadata
title : Silverlight 2.0 Hello World Application
author : Sergey Pugachev
copyright :
comment :
WMFSDKVersion : 11.0.6001.7000
WMFSDKNeeded : 0.0.0.0000
IsVBR : 1
ASFLeakyBucketPairs:
VBR Peak : 715351
Buffer Average : 127036
At least one output file must be specified
But I cant figure how to script this and capture output to any kind of posh objects.
I tried direct script, wher ps1 file contained exact expression "d:\video.Enc\ffmpeg.exe -i d:\video.Enc\1.wmv" - it didnt work. Also i tried to do that with invoke-command and invoke expression. First one returns an exact string with command, second one - dump error to output console but not to -ErrorVariable i specified ( I did set all out variables, not only error one - all of them were empty).
Can anyone point to correct syntax for invoking console applications in posh and capturing output ?
Second one question will be about parsing that output - I'll need video resolution data to calculate correct aspect ratio for conversion. So it will be cool if anyone point how to work with captured error output and parse string like
Stream #0.1(eng): Video: wmv3, yuv420p, 1024x768,
Try redirecting the error stream to stdout like so and then you should be able to capture both stdout and stderr in a single variable e.g.:
$res = d:\video.Enc\ffmpeg.exe -i d:\video.Enc\1.wmv 2>&1
To capture the data try this:
$res | Select-String '(?ims)^Stream.*?(\d{3,4}x\d{3,4})' -all |
%{$_.matches} | %{$_.Groups[1].Value}
I'm not sure if $res will be one string or multiple but the above should work for both cases.