Log in

View Full Version : video encoded with x264 plays too fast


Conquerist
6th May 2007, 06:07
Hi,
I am trying to encode movies and video files, some of which are in x264+ac3 mkv and some are xvid+vbr mp3 avis, to an ipod. I am personnaly not a big fan of apple and their products, but this is my dad's and i'm just trying to do him a favor. iTunes and converters such as videora have caused me such annoyance that i've written my own batch script to transcode files to x264+aac mp4.

Here's the script (the input file is %1, which I just drag and drop onto the batch file's icon):

@echo off
::set working directory
F:
cd "temp\ipod x264"

::find aspect ratio and crop accordingly
::get width
MediaInfo.exe --Inform=Video;file://x.txt %1 > tempfile
copy setx.bat + tempfile $tmp$.bat > nul
call $tmp$.bat
del $tmp$.bat
del tempfile

::get hight
MediaInfo.exe --Inform=Video;file://y.txt %1 > tempfile
copy sety.bat + tempfile $tmp$.bat > nul
call $tmp$.bat
del $tmp$.bat
del tempfile

::calculate new height to crop file to 320xYYY. i could also encode it at 320x240 and use a SAR flag,
but that doesn't make sense, because the ipod screen is only 320x240 big.
set /a ar = (1000 * x) / y
set /a resy = (320 * 1000) / ar

::find out if a space is in a filename, because otherwise avisynth goes crazy with missing/not missing quotation marks
::this is necesarry because otherwise either files without or with spaces would not work. i've tried every combination
of carot marks and quotation marks around the %1 and i've found this to be the only working solution
set filename=%1
set quote=%filename:~-1%
set quote=%quote:"=%

::write avisynth scripts for the audio and the video
if %quote%a == a (
echo DirectShowSource^(%1^).BilinearResize^(320,%resy%^).ConvertToYV12^(^) > video.avs
echo DirectShowSource^(%1^).Normalize > audio.avs
)
if not %quote%a == a (
echo DirectShowSource^("%1"^).BilinearResize^(320,%resy%^).ConvertToYV12^(^) > video.avs
echo DirectShowSource^("%1"^).Normalize > audio.avs
)

::encode to ipod-spec h264 video in a mp4 container. modified based on megui ipod profile
x264 --pass 1 --bitrate 768 --stats ".stats" --level 1.3 --no-cabac --subme 6 --analyse p8x8,b8x8
--qpmin 16 --vbv-maxrate 768 --me umh --merange 12 --threads auto --thread-input --progress
--no-psnr --output NUL "F:\Temp\ipod x264\video.avs"

x264 --pass 2 --bitrate 768 --stats ".stats" --level 1.3 --no-cabac --subme 6 --analyse p8x8,b8x8
--qpmin 16 --vbv-maxrate 768 --me umh --merange 12 --threads auto --thread-input --progress
--no-psnr --output "F:\Temp\ipod x264\video.mp4" "F:\Temp\ipod x264\video.avs"

::encode audio into aac with the nero aac encoder
bepipe.exe --script "import(^audio.avs^)" | "neroAacEnc.exe" -br 128000 -lc -if - -of audio.mp4

::multiplex the audio and the video
MP4Box.exe -new -add video.mp4#video -add audio.mp4#audio muxed.mp4

::write the file-info, for debug purposes
mediainfo %1 > original.txt
mediainfo video.mp4 > video.txt
mediainfo audio.mp4 > audio.txt
mediainfo muxed.mp4 > muxed.txt

::keep temp files for debug purposes
goto end

::delete temp files
del .stats
del video.mp4
del audio.mp4
del video.avs
del audio.avs

:end
pause
Please say so if any part of the script seems unclear.

Enough of the introduction; Here's my problem: everything with x264+ac3 in mkv converts without problems. However, with avis, i get a big error!

First and foremost, the encoded video (both video.mp4 and muxed.mp4) plays too fast. The remaining time is filled with a repeat of the last second of video. I know that it is the video that plays too fast and not the audio that plays too slow, because i've tried all combinations of dubbing the original avi, the avs, video.mp4 (the x264 output) and muxed.mp4 (the mp4box output) with all audios (original avi, audio.avs, audio.mp4, muxed.mp4) using mpc's open file -> dub feature. All of the combinations which use either video.mp4 or muxed.mp4 for the video play too fast, which causes the audio to be out of sync. The error is along the scale of 1-2 second in a 21 minute file.

Even though I am not a 100% certain that x264 is to blame, I believe it is, because it is the output of x264, not of bepipe or avisynth or neroeaacenc or mp4box which causes the wrong output.

I thought that an incorrect fps in x264 was to blame. Therefore, I created the mediainfo > xxx.txt lines to see the fps at all stages of the conversion. It was always 23.976 (the NTSC framerate). So i don't think that's the cause of my problem. I even specified the framerate of 23.976 in x264 using the --fps switch and got the same problem.

The problem might also be vbr audio in avi, but because i use directshowsource (which uses directshow) and not avisource (which uses vfw) in avisynth, i don' think that's a problem either. I am sure it is not a problem, because dubbing the original avi file with audio.mp4 is in sync.

Does anyone know what my problem is?

Thank you for reading this long post and thanks in advance for all your solution/help/advice of which i've found so much just by searchign the doom9 forums. I apologize if this has been posted and answered before, but I couldn't find a similar problem using the search feature.

Attached is the output of the media info > txt functions. Note the inconsistent play lengths on all of the files.

PS: i get the same problem if i encode it using megui and use the integrated mp4box gui instead of my own script

HowlerX
6th May 2007, 07:30
I've seen this bug before. Unfortunately I didn't know what application was at fault. Like you I suspected x264's output which is why I used xvid_encraw for that particular file. I believed I also fixed it by using AVISource() as well on another troublesome file. It's probably a good idea to use AVISource when dealing with .avi's and DSSource for everything else.

check
6th May 2007, 10:42
are you decoding with coreavc 0.0.0.4? If so, it's probable that's the cause, and you should move to a legal version of coreavc, or ffdshow.

Conquerist
7th May 2007, 02:19
Thanks for the advice. I'm using CoreAVC 1.3. I'll try your guys' advice (avisource and using ffdshow) once I have a moment of free time.

Guest
7th May 2007, 04:08
you should move to a legal version of coreavc Please explain how to do that. Thank you.

check
7th May 2007, 07:14
1. Go to http://www.coreavc.com/
2. Attempt to find order button
3. ??????
4. PROFIT!

Judging by how long the "just a few days!" message has been up there, coreavc is off the market for good, and I've felt that way for a few months now. I suggested it anyway so that on the off chance it does come back up, at least the OP knows about it.

Conquerist
8th May 2007, 01:39
Thanks HowlerX!
Using Avisource fixed it :-). I initially thought it wouldn't work, because using the avs script with avisource was out of sync in mpc. But it looks like it all works out if you open it with x264.

About CoreAVC:
Version 1.3.0.0 is included in the k-lite codec pack and mega codec pack (http://www.codecguide.com). It's free in the pack. However I don't know if that is 100% legal, because k-lite mega pack also includes the codecs from quicktime pro, which normally cost money.

And the corecodec website is a real mess. There's coreavc.com, corecodec.com, and corecodec.org. I couldn't even find the buy link myself.

Of course, you can alternatively use ffdshow, which is catching up with decoding speed in recent builds.

dbzgundam
8th May 2007, 02:34
1. Go to http://www.coreavc.com/
2. Attempt to find order button
3. ??????
4. PROFIT!

Judging by how long the "just a few days!" message has been up there, coreavc is off the market for good, and I've felt that way for a few months now. I suggested it anyway so that on the off chance it does come back up, at least the OP knows about it.

Anonymous does not forgive. You're doing it wrong (there's 5 steps, no?).

Hopefully you'll get that. :D

Anyway, I had this problems practically over a year ago on some early x264 encodes... the problem was always framerate related (seemed to default to 25fps???) but seemed to be rectified with a timecode file inside an MKV. Eventually the problem disappeared for me with newer MeGUI and x264 builds, so you'd have to ask a dev about that one...

And I had no idea CoreAVC wasn't being sold right now. Something going on there?

Conquerist
8th May 2007, 04:18
Anyway, I had this problems practically over a year ago on some early x264 encodes... the problem was always framerate related (seemed to default to 25fps???) but seemed to be rectified with a timecode file inside an MKV. Eventually the problem disappeared for me with newer MeGUI and x264 builds, so you'd have to ask a dev about that one...

Using Avisource fixed it :-). I initially thought it wouldn't work, because using the avs script with avisource was out of sync in mpc. But it looks like it all works out if you open it with x264.

Thanks, but I already got it working. It looks like the problem lies with using DirectShowSource() to frameserve an avi file to x264. Using AviSource() is a workaround that works great.

I also have updated my batch script in case any one is interested in it. It converts all DS-playable files to ipod 5g compatible h264+aac.


@echo off
::set working directory
F:
cd "temp\ipod x264"

::find aspect ratio and crop accordingly
::get width
MediaInfo.exe --Inform=Video;file://x.txt %1 > tempfile
copy setx.bat + tempfile $tmp$.bat > nul
call $tmp$.bat
del $tmp$.bat
del tempfile

::get hight
MediaInfo.exe --Inform=Video;file://y.txt %1 > tempfile
copy sety.bat + tempfile $tmp$.bat > nul
call $tmp$.bat
del $tmp$.bat
del tempfile

::calculate new height to crop file to 320x???
set /a ar = (1000 * x) / y
set /a resy = (320 * 1000) / ar

::make sure height is mod 2
set /a resy = %resy%*100/200*2

::Use AviSource with avis
if %~x1 == .avi (
echo AviSource^("%~1", false^).BilinearResize^(320,%resy%^).ConvertToYV12^(^) > "%~n1_video.avs"
echo AviSource^("%~1"^).Normalize > "%~n1_audio.avs"
)

::Use DSSource with everythign else
if not %~x1 == .avi (
echo DirectShowSource^("%~1", audio=false^).BilinearResize^(320,%resy%^).ConvertToYV12^(^) > "%~n1_video.avs"
echo DirectShowSource^("%~1", video=false^).Normalize > "%~n1_audio.avs"
)

::encode to ipod-spec h264 video in a mp4 container. modified based on megui ipod profile
x264 --pass 1 --bitrate 768 --stats "%~n1.stats" --level 1.3 --no-cabac --subme 6 --analyse p8x8,b8x8
--qpmin 16 --vbv-maxrate 768 --me umh --merange 12 --threads auto --thread-input --progress
--no-psnr --output NUL "F:\Temp\ipod x264\%~n1_video.avs"

x264 --pass 2 --bitrate 768 --stats "%~n1.stats" --level 1.3 --no-cabac --subme 6 --analyse p8x8,b8x8
--qpmin 16 --vbv-maxrate 768 --me umh --merange 12 --threads auto --thread-input --progress
--no-psnr --output "F:\Temp\ipod x264\%~n1_video.mp4" "F:\Temp\ipod x264\%~n1_video.avs"

::encode audio into aac with the nero aac encoder
bepipe.exe --script "import(^%~n1_audio.avs^)" | "neroAacEnc.exe" -br 128000 -lc -if - -of "%~n1_audio.mp4"

::multiplex the audio and the video
MP4Box.exe -new -add "%~n1_video.mp4#video" -add "%~n1_audio.mp4#audio" "%~n1.mp4"

::delete temp files
del %~n1.stats
del %~n1_video.mp4
del %~n1_audio.mp4
del %~n1_video.avs
del %~n1_audio.avs

I've simplified it a bunch and fixed a number of bugs, and sicne then I haven't had a singe problem with it. It converts everything i throw at it: filenames with spaces, vbr mp3 avis, and any other stuff that caused problems in the earlier version.

Off topic:
do you guys think I should make a thread and "advertise" this little batch script as a working ipod 5g video converter? I've already looked all over the place for one, and I've come across lot's of ones that don't fully work, and not a single working batch script.

ficofico
25th June 2007, 12:52
I've crated a batch file:

x264.exe ""istruzioni.avs"" --pass 1 --bitrate 4000 --stats ".stats" --ref 16 --mixed-refs --no-fast-pskip --bframes 3 --b-pyramid --b-rdo --bime --weightb --direct auto --filter -2,-1 --subme 7 --trellis 2 --analyse none --vbv-maxrate 25000 --me umh --threads auto --thread-input --progress --no-dct-decimate --no-psnr --no-ssim --output NUL ""
x264.exe ""istruzioni.avs"" --pass 2 --bitrate 4000 --stats ".stats" --ref 16 --mixed-refs --no-fast-pskip --bframes 3 --b-pyramid --b-rdo --bime --weightb --direct auto --filter -2,-1 --subme 7 --trellis 2 --analyse none --vbv-maxrate 25000 --me umh --threads auto --thread-input --progress --no-dct-decimate --no-psnr --no-ssim -o "intermedio.mp4"

mp4box -raw 2 "originale.mp4"

MP4Box -add "intermedio.mp4:delay=1000" -add "originale_track2.aac" "finito.mp4"

del intermedio.mp4
del originale_track2.aac
@echo Finished!

In this batch I want to put this string at first line:

MediaInfo "--Inform=Video; %FrameRate%" ; "originale.mp4" > framerate.txt

But mediainfo give me an empty file. If I open the shell and past the script work.... why?

Conquerist
25th June 2007, 19:36
Ficofico, I have had the same problem as you and it has caused lots of trouble as well. The problem lies with the use of %asdf% in the variable name of a batch script. If you use MediaInfo "--Inform=Video; %FrameRate%" ; "originale.mp4" > framerate.txt in the cmd, it works, because %FrameRate% is treated as a string of text. However, within a batch script, the %FrameRate% is treated as a variable, which is empty. Thus, MediaInfo.exe only sees "--Inform=Video; " ; "originale.mp4".

To fix that, you have to do the same thing I did. You need to create a file (fps.txt), which only has %FrameRate% in it. So what you get is:


MediaInfo.exe --Inform=Video;file://fps.txt originale.mp4 > framerate.txt


To clear up the confusion of the text files, fps.txt has %FrameRate% in it, and framerate.txt will have the actual framerate in a number in it (such as 23.976).

Now, if you want to use the number in framerate.txt as a variable in calling anothe program, you need another few steps. I've tried all simpler ways, and this is the only way I found which works. You need a file called setfps.bat which only has set fps= in it.


MediaInfo.exe --Inform=Video;file://fps.txt originale.mp4 > framerate.txt
copy setfps.bat + framerate.txt $tmp$.bat > nul
call $tmp$.bat
del $tmp$.bat

Now you can use %fps% in calling any program such as mp4box or x264 to parse the framerate!

That's as simple as I can put it. I hope it helps. Please do reply if it works for you or not.

ficofico
25th June 2007, 20:12
Great!!!!!!!!!!! The second part of your post it's very usefull. For the first part I've pass 10-11 ours with google and finally I've found a way to extract the framerate:

I've modified the script with this line:
cmd.exe < testo.txt


x264.exe ""istruzioni.avs"" --pass 1 --bitrate 4000 --stats ".stats" --ref 16 --mixed-refs --no-fast-pskip --bframes 3 --b-pyramid --b-rdo --bime --weightb --direct auto --filter -2,-1 --subme 7 --trellis 2 --analyse none --vbv-maxrate 25000 --me umh --threads auto --thread-input --progress --no-dct-decimate --no-psnr --no-ssim --output NUL ""
x264.exe ""istruzioni.avs"" --pass 2 --bitrate 4000 --stats ".stats" --ref 16 --mixed-refs --no-fast-pskip --bframes 3 --b-pyramid --b-rdo --bime --weightb --direct auto --filter -2,-1 --subme 7 --trellis 2 --analyse none --vbv-maxrate 25000 --me umh --threads auto --thread-input --progress --no-dct-decimate --no-psnr --no-ssim -o "intermedio.mp4"

mp4box -raw 2 "originale.mp4"

MP4Box -add "intermedio.mp4:delay=1000" -add "originale_track2.aac" "finito.mp4"

del intermedio.mp4
del originale_track2.aac
del framerate.txt
@echo Finished!

where testo.txt have inside the string parameters for mediainfo!!! ((MediaInfo "--Inform=Video; %FrameRate%" ; "originale.mp4" > framerate.txt))

2 ways for the same result but, I'm very tired now!!!!

now I try to use your second example for my batch app. Very thanks!