Video transcode and codec issue - ffmpeg

I'm converting some old videos to play on my Roku via a dlna server. I'm trying to understand the MP4 container better to optimize conversions. I have an ogm video:
Duration: 01:00:38.22, start: 0.000000, bitrate: 1056 kb/s
Stream #0:0: Video: mpeg4 (XVID / 0x44495658), yuv420p, 576x324 [SAR 1:1 DAR 16:9], 23.98 fps, 23.98 tbr, 23.98 tbn, 23.98 tbc
Stream #0:1(English): Audio: aac, 48000 Hz, stereo, fltp, 74 kb/s
Stream #0:2(Japanese): Audio: aac, 48000 Hz, stereo, fltp, 73 kb/s
Stream #0:3(English): Subtitle: text
From what I understand, MP4 container can contain MP4 video and aac audio. I used
-c:a copy -c:v copy
And it worked, but the video won't play. Obviously something's wrong. What I don't understand is why, the video looks like it's MP4 and the audio is aac. My guess is it's the Xvid but why?
Thank you.
Todd

MP4 is only the container but your right MP4 usually contain AAC audio and MPEG4 video. Your input file seems to be mpeg4 Xvid which is a mpeg4 derived codec but might not be supported by Roku.
Try change -c:v copy to -c:v h264 to use a more common MPEG4 based video codec.

Related

How to Transcode ALL Audio streams from input to output using ffmpeg?

I have an input MPEG TS file 'unit_test.ts'. This file has following content (shown by ffprobe):
Input #0, mpegts, from 'unit_test.ts':
Duration: 00:00:57.23, start: 73674.049844, bitrate: 2401 kb/s
Program 1
Metadata:
service_name : Service01
service_provider: FFmpeg
Stream #0:0[0x31]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(progressive), 852x480 [SAR 640:639 DAR 16:9], Closed Captions, 59.94 fps, 59.94 tbr, 90k tbn, 119.88 tbc
Stream #0:1[0x34](eng): Audio: ac3 ([129][0][0][0] / 0x0081), 48000 Hz, 5.1(side), fltp, 448 kb/s
Stream #0:2[0x35](spa): Audio: ac3 ([129][0][0][0] / 0x0081), 48000 Hz, stereo, fltp, 192 kb/s
I want to convert it into another MPEG TS file. Requirement is that the Video stream of the input should be directly copied to the output whereas ALL the audio streams should be transcoded "aac" format.
I tried this command:
ffmpeg -i unit_test.ts -map 0 -c copy -c:a aac maud_test.ts
It converted it into 'maud_test.ts' with following contents (shown by ffprobe)
Input #0, mpegts, from 'maud_test.ts':
Duration: 00:00:57.25, start: 1.400000, bitrate: 2211 kb/s
Program 1
Metadata:
service_name : Service01
service_provider: FFmpeg
Stream #0:0[0x100]: Video: h264 (Main) ([27][0][0][0] / 0x001B), yuv420p(progressive), 852x480 [SAR 640:639 DAR 16:9], Closed Captions, 59.94 fps, 59.94 tbr, 90k tbn, 119.88 tbc
Stream #0:1[0x101](eng): Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, 6 channels, fltp, 391 kb/s
Stream #0:2[0x102](spa): Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 133 kb/s
So it appeared as if the command worked....However when I play the maud_test.ts file in vlc player I can see both audio streams listed in the menu; but Stream 1 (eng) remains silent............whereas Stream 2 (spa) has proper audio. (Original TS file has both audio streams properly audible)
I have tried this with different input files and have seen that same problem occurs in each case.
What that I am doing is not right?
How should I get this done? (I can write explicit stream by stream map and channel arguments to get that done; however I want the command line to be generic, in that the input file could be having any configuration with one Video and several Audios with different formats. The configuration will not be known beforehand.)

Concatenate no audio video with other videos containing audio,

I have a txt file which contains several videos:
file '01.mp4' # No audio, only video
file '02.mp4' # Video with audio
...
All my videos are using same video codecs:
Stream #0:0[0x1](und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709, progressive), 720x1280, 3167 kb/s, 30 fps, 30 tbr, 15360 tbn (default)
And all my video that contains audio are these codecs:
Stream #0:1[0x2](und): Audio: aac (HE-AAC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 43 kb/s (default)
I tried to add silent audio using:
ffmpeg -f lavfi -i anullsrc=channel_layout=stereo:sample_rate=44100 -i 01.mp4 -c:v copy -c:a aac -shortest 01-silentaudio.mp4
But when concatening all my videos, it results in no audio for all videos.
What should I do?
Maybe I can reencode all my video to a specific codec, including my video without sound, in order to have the same codecs for all? What do you think?
Thank you

ffmpeg overlay whith audio filter showcqt

I want to overlay a video with the showcqt effect on the right corner, I know that I have to use a filter graph but don't know how, the documentation is large but not very accessible for me. ffmpeg outputs this:
Input #0, matroska,webm, from 'cover.webm':
Metadata:
ENCODER : Lavf58.20.100
Duration: 00:03:14.58, start: -0.007000, bitrate: 206 kb/s
Stream #0:0(eng): Video: vp9 (Profile 0), yuv420p(tv, bt709), 1280x720, SAR 1:1 DAR 16:9, 24 fps, 24 tbr, 1k tbn, 1k tbc (default)
Metadata:
DURATION : 00:03:14.541000000
Stream #0:1(eng): Audio: opus, 48000 Hz, stereo, fltp (default)
Metadata:
DURATION : 00:03:14.581000000
You can use the showcqt and overlay filters:
ffmpeg -i input.webm -filter_complex "showcqt=s=320x180[cqt];[0][cqt]overlay=main_w-overlay_w:main_h-overlay_h" -c:a copy output.webm
The audio is stream copied (-c:a copy) in this example to avoid re-encoding. Remove -c:a copy if you want it to automatically re-encode to an appropriate audio format for whatever output container you choose.

How to process a video to mp4 with ffmpeg for quality and compatibility?

I am beginning to be more serious about video. I am processing my videos with ffmpeg in a fully updated Linux into mp4 to use it in HTML5 directly.
Now, I have old AVI videos that I want to convert to mp4 with ffmpeg for use with HTML5. In particular, I have this one:
http://luis.impa.br/photo/1101_aves_ce/caneleiro-de-chapeu-preto_femea_Quixada-CE-110126-E_05662+7a.avi
(I know, terrible quality... sorry). According to ffprobe:
Duration: 00:01:35.30, start: 0.000000, bitrate: 1284 kb/s
Stream #0:0: Video: mpeg4 (Simple Profile) (DX50 / 0x30355844), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 1144 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc
Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 44100 Hz, stereo, s16p, 128 kb/s
That seems perfect: mpeg4 video and mp3 audio. So I tried:
ffmpeg -i input.avi -acodec copy -vcodec copy output.mp4
It generates a file that plays nicely in mplayer, but not in firefox getting an error:
Video format or MIME type not supported.
Chrome plays the audio, but no video is shown... Now, if I do:
ffmpeg -i input.avi output.mp4
firefox works, but the video is reencoded in another one with half the size (half the bitrate). This is what ffprobe says about the reencoded video:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.71.100
Duration: 00:01:35.30, start: 0.000000, bitrate: 685 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 548 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
I suppose that I am loosing lots of quality (and time processing the video). So, my questions:
Why are browsers not playing my video with the copy codecs ?
Can I work with ffmpeg in this particular file without reencoding? If yes, how?
If I need to reencode, which are "reasonable" parameters to keep close to the original quality? Would something like
ffmpeg -i input.avi -b:v 1024k -bufsize 1024k output.mp4
suffice for this video? This generates a new video with size closer to the original one.
Thanks!
According to ffprobe and if I see it correctly, you have a DivX (5) video file. Do not use it for web!! ;)
mpeg4 (Simple Profile) (DX50 / 0x30355844)
So I don't see any chance to use this video without reencoding. Not if you wish to support firefox.
Use WebM or h264: https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
UPDATE
Good settings for reencode depends on your input (bitrate, resolution, fps, kind of material ...), so there is no standard answer.
But you have to specify a codec or ffmpeg choose one depending on your output file extension (so it can be the wrong one).
You can try this:
ffmpeg -i input.avi -c:v libx264 -preset slow -crf 22 -c:a copy output.mkv
Presets and tunes can help to find the best choice: https://trac.ffmpeg.org/wiki/Encode/H.264

Frame rate control of a ts file

I have a ts file, which is created by encoding raw yuv data using x264enc and muxing it with mpegtsmux.
And this file contains more than one stream. For example it may contain two video streams, or it may contain two video and one text stream like that.
It is of 25 fps, and 720X576 resolution. I would like to change it's fps to say 10, and all the three streams must present in the new ts file also.
Is there any pipeline for this in gstreamer? or any command in ffmpeg? How can i do this?
I don't think that this is possible in GStreamer. At least is not straightforward. However, it should be possible with ffmpeg as long as all the sequences in the file can be discovered correctly.
From the wiki of ffmpeg, map option (https://trac.ffmpeg.org/wiki/Map):
The "map" command basically means "include this stream into the
immediately following OUTPUT file."
Using map option it is possible to re-encode the video stream that you want and keep untouched the others.
Using input.ts file as an example with 2 different video streams and some audio streams, the way to follow should be the next:
ffmpeg -i input.ts -map 0:0 -map 0:2 -map 0:3 -map 0:4 -map 0:23 -map 0:10 -map 0:14 -c:v:0 mpeg2video -r:v:0 10 -c:v:1 copy -c:a copy outputmini.ts
Note that the video streams are 0:0 and 0:23. The first video stream (mpeg2) is re-encoded to 10 fps whereas the 0:23 video stream (x264) is just copied to the output. Remember that if there is some unknown stream in the .ts file you may need to add -ignore_unknown flag.
As specified in the link from ffmpeg, the output stream order is specified in the command execution in the map option placement order. With -c:v:0 mpeg2video option, we select the first output video stream and re-encoding codec, while the -r:v:0 10 option puts the first video stream frame rate to 10 fps. The other options from the command line copies the input stream to output with the same parameters.
ffmpeg outputs next:
Output #0, mpegts, to 'outputmini.ts':
Metadata:
encoder : Lavf57.41.100
Stream #0:0: Video: mpeg2video (Main), yuv420p, 640x576 [SAR 6:5 DAR 4:3], q=2-31, 200 kb/s, 10 fps, 90k tbn, 10 tbc
Metadata:
encoder : Lavc57.50.100 mpeg2video
Side data:
cpb: bitrate max/min/avg: 0/0/200000 buffer size: 0 vbv_delay: -1
Stream #0:1(spa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, 192 kb/s
Stream #0:2(qaa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, stereo, 192 kb/s
Stream #0:3(spa): Audio: mp2 ([3][0][0][0] / 0x0003), 48000 Hz, mono, 96 kb/s (visual impaired)
Stream #0:4: Video: h264 ([27][0][0][0] / 0x001B), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], q=2-31, 50 fps, 50 tbr, 90k tbn, 90k tbc
Stream #0:5(spa): Audio: eac3 ([6][0][0][0] / 0x0006), 48000 Hz, stereo, 256 kb/s
Stream #0:6(spa): Audio: eac3 ([6][0][0][0] / 0x0006), 48000 Hz, mono, 64 kb/s (visual impaired)
Stream mapping:
Stream #0:0 -> #0:0 (mpeg2video (native) -> mpeg2video (native))
Stream #0:2 -> #0:1 (copy)
Stream #0:3 -> #0:2 (copy)
Stream #0:4 -> #0:3 (copy)
Stream #0:23 -> #0:4 (copy)
Stream #0:10 -> #0:5 (copy)
Stream #0:14 -> #0:6 (copy)
The desired output is achieved.
However, even though I'm not sure this could be done, I would get a glimpse to tsMuxeR appllication (http://www.videohelp.com/software/tsMuxeR). It is a very powerful tool to this kind of tasks.

Resources