4

I am trying to convert some old movie files to images (and later to reencode as h.264). The problem is that the resulting images are stretched vertically.

Here is the ffmpeg command:

ffmpeg -i preview.mpg -filter_complex "[0:v]fps=fps=1[onepersec]; [onepersec]scale=min(200\, iw):-2[rescaled]" -map "[rescaled]" -f image2 image%4d.jpg

I have a guess: the scale filter as I use it ignores the display aspect ratio DAR and simply scales the pixel values. I want the width of the images to be at most 200 pixels and the height can be whatever it needs to be as long as it looks right, i.e., not stretched.

How should I convert the movie file to get images (and re-encoded video) that do not look stretched?

Additional info about the video file:

In VLC it plays back looking ok. It looks like a normal 4:3 aspect ratio. VLC displays the following in Current media information > Codec:

Stream 0
Type: Video
Codec: MPEG-1/2 Video (mpgv)
Resolution: 352x576
Frame rate: 25
Decoded format: Planar 4:2:0 YUV

Here is the output from running the above ffmpeg command:

ffmpeg version git-2014-07-24-f753956 Copyright (c) 2000-2014 the FFmpeg developers
  built on Jul 24 2014 13:39:56 with gcc 4.4.7 (GCC) 20120313 (Red Hat 4.4.7-4)
  configuration: --prefix=/home/somename/ffmpeg_build --extra-cflags=-I/home/somename/ffmpeg_build/include --extra-ldflags=-L/home/somename/ffmpeg_build/lib --bindir=/home/somename/bin --extra-libs=-ldl --enable-gpl --enable-nonfree --enable-libfdk_aac --enable-libmp3la
me --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libfreetype --enable-libspeex --enable-libtheora
  libavutil      52. 92.101 / 52. 92.101
  libavcodec     55. 69.100 / 55. 69.100
  libavformat    55. 49.100 / 55. 49.100
  libavdevice    55. 13.102 / 55. 13.102
  libavfilter     4. 11.102 /  4. 11.102
  libswscale      2.  6.100 /  2.  6.100
  libswresample   0. 19.100 /  0. 19.100
  libpostproc    52.  3.100 / 52.  3.100
Input #0, mpeg, from 'preview.mpg':
  Duration: 00:14:23.59, start: 1.646067, bitrate: 2244 kb/s
    Stream #0:0[0x1bf]: Data: dvd_nav_packet
    Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv), 352x576 [SAR 24:11 DAR 4:3], max. 2500 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:2[0x80]: Audio: ac3, 48000 Hz, stereo, fltp, 256 kb/s
[swscaler @ 0x3f6fae0] deprecated pixel format used, make sure you did set range correctly
Output #0, image2, to 'image%4d.jpg':
  Metadata:
    encoder         : Lavf55.49.100
    Stream #0:0: Video: mjpeg, yuvj420p, 200x328 [SAR 164:75 DAR 4:3], q=2-31, 200 kb/s, 1 fps, 1 tbn, 1 tbc
    Metadata:
      encoder         : Lavc55.69.100 mjpeg
Stream mapping:
  Stream #0:1 (mpeg2video) -> fps
  scale -> Stream #0:0 (mjpeg)
Press [q] to stop, [?] for help
frame=   41 fps=0.0 q=1.6 size=N/A time=00:00:41.00 bitrate=N/A    ^Mframe=   80 fps= 79 q=1.6 size=N/A time=00:01:20.00 bitrate=N/A    ^Mframe=  125 fps= 71 q=1.6 size=N/A time=00:02:05.00 bitrate=N/A    ^Mframe=  156 fps= 69 q=1.6 size=N/A time=00:02:36.00 bitrate=N/A    ^Mframe=  203 fps= 74 q=1.6 size=N/A time=00:03:23.00 bitrate=N/A    ^Mframe=  248 fps= 76 q=1.6 size=N/A time=00:04:08.00 bitrate=N/A    ^Mframe=  295 fps= 79 q=1.6 size=N/A time=00:04:55.00 bitrate=N/A    ^Mframe=  336 fps= 79 q=1.6 size=N/A time=00:05:36.00 bitrate=N/A    ^Mframe=  377 fps= 79 q=1.6 size=N/A time=00:06:17.00 bitrate=N/A    ^Mframe=  424 fps= 81 q=1.6 size=N/A time=00:07:04.00 bitrate=N/A    ^Mframe=  465 fps= 81 q=1.6 size=N/A time=00:07:45.00 bitrate=N/A    ^Mframe=  508 fps= 81 q=1.6 size=N/A time=00:08:28.00 bitrate=N/A    ^Mframe=  547 fps= 79 q=1.6 size=N/A time=00:09:07.00 bitrate=N/A    ^Mframe=  580 fps= 78 q=1.6 size=N/A time=00:09:40.00 bitrate=N/A    ^Mframe=  621 fps= 79 q=1.6 size=N/A time=00:10:21.00 bitrate=N/A    ^Mframe=  665 fps= 79 q=1.6 size=N/A time=00:11:05.00 bitrate=N/A    ^Mframe=  709 fps= 80 q=1.6 size=N/A time=00:11:49.00 bitrate=N/A    ^Mframe=  746 fps= 79 q=1.6 size=N/A time=00:12:26.00 bitrate=N/A    ^Mframe=  794 fps= 80 q=1.6 size=N/A time=00:13:14.00 bitrate=N/A
^Mframe=  833 fps= 80 q=1.6 size=N/A time=00:13:53.00 bitrate=N/A    ^Mframe=  865 fps= 81 q=1.6 Lsize=N/A time=00:14:25.00 bitrate=N/A
video:11118kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: unknown

Maybe I need to do something about [swscaler @ 0x3f6fae0] deprecated pixel format used, make sure you did set range correctly?

Here is output from mediainfo:

$ mediainfo preview.mpg
General
Complete name                            : /[...]/preview.mpg
Format                                   : MPEG-PS
File size                                : 231 MiB
Duration                                 : 14mn 23s
Overall bit rate mode                    : Variable
Overall bit rate                         : 2 244 Kbps

Video
ID                                       : 224 (0xE0)
Format                                   : MPEG Video
Format version                           : Version 2
Format profile                           : Main@Main
Format settings, BVOP                    : Yes
Format settings, Matrix                  : Custom
Format settings, GOP                     : M=2, N=12
Duration                                 : 14mn 23s
Bit rate mode                            : Variable
Bit rate                                 : 1 943 Kbps
Maximum bit rate                         : 2 500 Kbps
Width                                    : 352 pixels
Height                                   : 576 pixels
Display aspect ratio                     : 4:3
Frame rate                               : 25.000 fps
Standard                                 : PAL
Color space                              : YUV
Chroma subsampling                       : 4:2:0
Bit depth                                : 8 bits
Scan type                                : Interlaced
Scan order                               : Top Field First
Compression mode                         : Lossy
Bits/(Pixel*Frame)                       : 0.383
Time code of first frame                 : 00:00:00:12
Time code source                         : Group of pictures header
Stream size                              : 200 MiB (87%)

Audio
ID                                       : 189 (0xBD)-128 (0x80)
Format                                   : AC-3
Format/Info                              : Audio Coding 3
Mode extension                           : CM (complete main)
Format settings, Endianness              : Big
Muxing mode                              : DVD-Video
Duration                                 : 14mn 23s
Bit rate mode                            : Constant
Bit rate                                 : 256 Kbps
Channel(s)                               : 2 channels
Channel positions                        : Front: L R
Sampling rate                            : 48.0 KHz
Bit depth                                : 16 bits
Compression mode                         : Lossy
Delay relative to video                  : -31ms
Stream size                              : 26.3 MiB (11%)

Menu

Here is output from ffprobe:

$ ffprobe preview.mpg
ffprobe version git-2014-07-24-f753956 Copyright (c) 2007-2014 the FFmpeg developers
  built on Jul 24 2014 13:39:56 with gcc 4.4.7 (GCC) 20120313 (Red Hat 4.4.7-4)
  configuration: --prefix=/home/sadmin/ffmpeg_build --extra-cflags=-I/home/somename/ffmpeg_build/include --extra-ldflags=-L/home/somename/ffmpeg_build/lib --bindir=/home/somename/bin --extra-libs=-ldl --enable-gpl --enable-nonfree --enable-libfdk_aac --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libfreetype --enable-libspeex --enable-libtheora
  libavutil      52. 92.101 / 52. 92.101
  libavcodec     55. 69.100 / 55. 69.100
  libavformat    55. 49.100 / 55. 49.100
  libavdevice    55. 13.102 / 55. 13.102
  libavfilter     4. 11.102 /  4. 11.102
  libswscale      2.  6.100 /  2.  6.100
  libswresample   0. 19.100 /  0. 19.100
  libpostproc    52.  3.100 / 52.  3.100
Input #0, mpeg, from 'preview.mpg':
  Duration: 00:14:23.59, start: 1.646067, bitrate: 2244 kb/s
    Stream #0:0[0x1bf]: Data: dvd_nav_packet
    Stream #0:1[0x1e0]: Video: mpeg2video (Main), yuv420p(tv), 352x576 [SAR 24:11 DAR 4:3], max. 2500 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc
    Stream #0:2[0x80]: Audio: ac3, 48000 Hz, stereo, fltp, 256 kb/s
Unsupported codec with id 1145979222 for input stream 0
$

Here the text Unsupported codec with id 1145979222 for input stream 0 is highlighted. I guess it is about Stream #0.0(?) which I do not need.

Here is what I get for one of the images:

$ ffprobe image0001.jpg
ffprobe version git-2014-07-24-f753956 Copyright (c) 2007-2014 the FFmpeg developers
  built on Jul 24 2014 13:39:56 with gcc 4.4.7 (GCC) 20120313 (Red Hat 4.4.7-4)
  configuration: --prefix=/home/somename/ffmpeg_build --extra-cflags=-I/home/somename/ffmpeg_build/include --extra-ldflags=-L/home/somename/ffmpeg_build/lib --bindir=/home/somename/bin --extra-libs=-ldl --enable-gpl --enable-nonfree --enable-libfdk_aac --enable-libmp3lame --enable-libopus --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libfreetype --enable-libspeex --enable-libtheora
  libavutil      52. 92.101 / 52. 92.101
  libavcodec     55. 69.100 / 55. 69.100
  libavformat    55. 49.100 / 55. 49.100
  libavdevice    55. 13.102 / 55. 13.102
  libavfilter     4. 11.102 /  4. 11.102
  libswscale      2.  6.100 /  2.  6.100
  libswresample   0. 19.100 /  0. 19.100
  libpostproc    52.  3.100 / 52.  3.100
[mjpeg @ 0x24c7e40] ignoring invalid SAR: 164/75
Input #0, image2, from 'mov0001.jpg':
  Duration: 00:00:00.04, start: 0.000000, bitrate: N/A
    Stream #0:0: Video: mjpeg, yuvj420p(pc, bt470bg), 200x328, 25 tbr, 25 tbn, 25 tbc

Interesting here could be [mjpeg @ 0x24c7e40] ignoring invalid SAR: 164/75 but what does that mean?

2 Answers 2

7

7 Years later and Im facing a similar issue, will drop a solution here for the people visiting in the next 7 years.

First try and get a better understanding of what SAR/PAR and DAR values mean. Nice youtube videos on the topic.

It will then make sense that when converting videos that have SAR values other than 1. It is important to first normalise the video (aka square the pixels) to conform with a SAR of 1/1.

The root cause of the image being stretched, is apparently most image viewing software do not care to read/understand SAR values. They expect SAR to be 1/1.

One method of achieving this is through the scale filter:

scale=iw*sar:ih

a generic ffmpeg example:

ffmpeg -i somefile.avi -vf 'scale=iw*sar:ih' someoutput%04d.jpg

This scales the width while maintaining the height to ensure SAR is now 1/1.

you could then add another scale step to get the desired dimensions:

scale=iw*sar:ih,scale=200:-2

or using the older filter notation as shown in the question:

-filter_complex "[0:v]fps=fps=1[onepersec]; [onepersec]scale=iw*sar:ih[onepersecondnorm]; [onepersecnorm]scale=min(200\, iw):-2[rescaled]"

Hoping this helped someone.

2
  • Thanks, this actually pointed me in the right direction, to add: I found that if generating a JPG, you need to add setsar=1:1 at the end of the filter chain, as such: ffmpeg -i in_file.mp4 -vf 'scale=iw*sar:ih,scale=w=320:h=240:force_original_aspect_ratio=decrease,setsar=1:1' -vframes 1 out_file.jpg Otherwise the the jpg still has the wrong aspect ratio, because ffmpeg doesn't seem put out SAR of 1:1 unless explicitly told to do so, even though jpg doesn't support anything else (i think) Nov 11, 2022 at 9:38
  • Thank for you double-scale-filter trick, exactly what I was after. Aug 19, 2023 at 16:13
1

@QuickPrototype - I found your answer a bit frustrating since understanding solutions in a way that allows one to apply it to similar situations often requires understanding the problem, and your post didn't really describe the SAR/PAR/DAR problem very well. It just simply told us to research it on Youtube.

Not finding any helpful YouTube videos, I found the following wikipedia article very enlightening: Pixel aspect ratio

The idea of image pixels (i.e. the smallest point of image data) and their aspect ratio (i.e the ratio of image/pixel/screen size in terms of 'width/height' sometimes expressed as 'width:height') arose from producing digital versions of analog video recordings. Analog video recordings had 'lines' and a 'center point' which worked well with the old Cathode Ray Tube televisions with a 4:3 aspect ratio that were used back in the day. There were no pixels in analog video recordings which were designed to guide a sweeping photon beam across the screen to light up phosphor on the screen sweeping from left to right and then down a line to the next line until all 525 lines on an NTSC (US) television (or 635 lines for European PAL or SECAM) were drawn and then the process started over to produce a series of 25 or 30 flickering images per second which creates the illusion for the human eye of motion. Digital recordings, instead, used a grid of 'pixels' to map the analog images to LCD screen technology or some other modern television flat panel technology.

Transcoding Problems happen when an analog video recording for an old TV cathode ray tube screen with a 4:3 width by height (DAR) 'display aspect ratio' is digitalized and then displayed on a flat panel TV with a 16:9 'display aspect ratio'. The resulting image might be black banded on the left and right sides to compensate for the different DAR ratios (4:3 versus 16:9) or the 4:3 image could be stretched to fill the full width, which meant either cropping the top and bottom of the image or possibly squeezing the image's height. Whether one refers to squeezing an image's height or stretching an image's width doesn't really matter as the result is basically the same in practice; however, the result produced can be a 4:3 image looking bizarrely-stretched to fit a 16:9 DAR screen and is generally not the recommended solution. Black banding or minimal cropping looks better because people's faces aren't squeezed or stretched.

From a technical standpoint digital 'stretching' or 'squeezing' is a result of not having a 'square' pixel of 1x1 units square each; instead a hypothetical pixel could be stretched or squeezed to say a rectangular "1.33 by 1 units" or "1 by 0.75 units" pixel. Anytime the (PAR) 'pixel aspect ratio' is not square, but rectangular, then the resulting image can look stretched or squeezed.

Mathematically this can be expressed by the following formulas:

'SAR x PAR = DAR' .. and .. 'PAR = DAR/SAR' (i.e. if PAR = 1 then SAR = DAR) where:

SAR = 'Storage Aspect Ratio' is an image's width and height in pixels, often stored in a digital file format.

PAR = 'Pixel Aspect Ratio' is a pixel's ratio of its width and height, which should normally be 1:1 (i.e. square) or else 'stretching' and 'squeezing' effects occur.

DAR = 'Display Aspect Ratio' is a screen's ratio of its width and height, which is hardwired into the screen's hardware itself.

Now to describe My Encountered Problem: 'Stretchiness' or its opposite 'squeezing' is a problem I ran into with digital video transcoding. When trying to 'standardise' non-standard resolutions that arose from laptop screen recordings with odd resolutions such as 1197x989 which I then attempted to scale to a more 'standard' aspect ratio using the ffmpeg filter '-vf scale=960:720' or '-vf scale=1440:1080' for example, I would find the output file with the height scaled (i.e. 'squeezed' to 720 pixels or 'stretched' to 1080 pixels) correctly but the width incorrectly 'squeezed' to 871 pixels instead of 960 pixels or incorrectly 'stretched' to only 1307 pixels instead of 1440 pixels which did not achieve the desired DAR display aspect ratio of 4:3. In effect, instead of applying a 4:3 DAR, ffmpeg was using the old SAR of 1197:989 to define the DAR and the -vf scale=value:value filter was only scaling the image to the desired height correctly, but not the width.

Frustrated, more research led me to the ffmpeg FAQ page, 3.18 I have a stretched video, why does scaling does not fix it? Here I was introduced to the ffmpeg filter: '-aspect 4:3' or '-aspect 16:9' which affected the width but not the height of the outputted image. When applying this filter, the height would remain 989 pixels, but the width would change to 1318 or 1758 pixels respectively. This looked even worse as the width 'stretching' was even more noticeable.

My Solution in the absence of not finding a specific ffmpeg PAR filter was to combine the above two filters (i.e. 'ffmpeg -i <input file> -vf scale=960:720 -aspect 4:3 <output file>' ... and ... 'ffmpeg -i <input file> -vf scale=1440:1080 -aspect 4:3 <output file>' ) which produced the desired 960x720 and 1440x1080 pixel video files respectively. The '-vf scale=value:value' effectively set the desired height of the output file in pixels while the '-aspect value:value' filter set the desired width of the output file in pixels.

Disclaimer: Of course, when converting non-standard aspect ratios to standard sizes, there must be some 'stretching' and/or 'squeezing' of the image when not using cropping or alternatively bandaiding as the black bands are sometimes called. The key is to ensure the resulting images are not abnormally bizarre looking which comes down to the appreciation of each viewer. If the non-standard size is fairly close to the standard size then the results I found were acceptable.

I hope this long-winded description of the problem and solution might be of help to other people who are grappling with image 'stretchiness'

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .