I am currently working on a project and almost ready to deploy, but there is one problem: the code which is working perfectly on my Ubuntu 16.04 (Elementary OS Loki) machine does not work in Docker container. What might be the problem in my code?
Here is my Dockerfile:
FROM beevelop/nodejs-python:latest
RUN apt-get -y update && apt-get install -y libav-tools
RUN ffmpeg --help
# Global install yarn package manager
RUN apt-get update && apt-get install -y curl apt-transport-https && \
curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - && \
echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list && \
apt-get update && apt-get install -y yarn
WORKDIR /app
COPY package.json .
RUN yarn
COPY . .
RUN yarn prod:build
EXPOSE 8080
CMD [ "yarn", "start" ]
I run sudo docker exec -it <container-name> ffmpeg --help
and it outputs the expected help print. In my code, I download a Youtube video in mp4 format with this code:
const download = idParam => (
new Promise((fulfill, reject) => {
const id = `http://www.youtube.com/watch?v=${idParam}`
let videoMeta
youtubedl(id, ['--format=36'], { cwd: __dirname })
.on('info', (info) => {
const customDimensions = calculateCustomDimensions(info.format)
videoMeta = { ...info, ...customDimensions }
})
.pipe(fs.createWriteStream(`temp/${idParam}.mp4`))
.on('finish', () => {
console.log('Dirname: ', __dirname)
fulfill(videoMeta)
})
.on('error', (err) => {
console.log('There is an error:', err)
console.log('Dirname: ', __dirname)
reject(err)
})
})
)
And then try to process the video with fluent-ffmpeg:
const processVideo = (videoName, cropStart, cropEnd) => (
new Promise((resolve, reject) => {
try {
console.log('Trying to run ffmpeg binary.')
ffmpeg()
.addInput(`temp/${videoName}.mp4`)
.seekInput(cropStart)
.duration(cropEnd)
.outputOption('-movflags frag_keyframe+faststart')
.on('end', () => {
console.log('Processing has finished with ffmpeg. ')
console.log('Resolved for upload: ', [`temp/cropped_${videoName}.mp4`, `temp/${videoName}.mp4`])
console.log('Going out of processVideo script.')
resolve([`temp/cropped_${videoName}.mp4`, `temp/${videoName}.mp4`])
})
.on('error', (err, stdout, stderr) => {
console.log('Error. Output option olmasına rağmen: ', err.message)
console.log('ffmpeg output:\n', stdout)
console.log('ffmpeg stderr:\n', stderr)
})
.save(`temp/cropped_${videoName}.mp4`)
} catch (e) {
console.log('There has been an error while converting ffmpeg binary!')
console.log(e.msg)
console.log(e.code)
reject(e)
}
})
)
It gives the following error:
Entering download script.
WARNING: Assuming --restrict-filenames since file system encoding cannot encode all characters. Set the LC_ALL environment variable to fix this.
`info.resolution` is deprecated, use `info.format`
Dirname: /app/lib/server/scripts
Download script is done.
Custom dimensions of the downloaded video: 320 180
Crop start and end of the downloaded video: 00:00:00.517 00:00:00.998
Entering processVideo script.
Trying to run ffmpeg binary.
Error: ffmpeg exited with code 1:
ffmpeg output:
ffmpeg stderr:
ffmpeg version 2.8.11-0ubuntu0.16.04.1 Copyright (c) 2000-2017 the FFmpeg developers
built with gcc 5.4.0 (Ubuntu 5.4.0-6ubuntu1~16.04.4) 20160609
configuration: --prefix=/usr --extra-version=0ubuntu0.16.04.1 --build-suffix=-ffmpeg --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --cc=cc --cxx=g++ --enable-gpl --enable-shared --disable-stripping --disable-decoder=libopenjpeg --disable-decoder=libschroedinger --enable-avresample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libmodplug --enable-libmp3lame --enable-libopenjpeg --enable-libopus --enable-libpulse --enable-librtmp --enable-libschroedinger --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-libxvid --enable-libzvbi --enable-openal --enable-opengl --enable-x11grab --enable-libdc1394 --enable-libiec61883 --enable-libzmq --enable-frei0r --enable-libx264 --enable-libopencv
libavutil 54. 31.100 / 54. 31.100
libavcodec 56. 60.100 / 56. 60.100
libavformat 56. 40.101 / 56. 40.101
libavdevice 56. 4.100 / 56. 4.100
libavfilter 5. 40.101 / 5. 40.101
libavresample 2. 1. 0 / 2. 1. 0
libswscale 3. 1.101 / 3. 1.101
libswresample 1. 2.101 / 1. 2.101
libpostproc 53. 3.100 / 53. 3.100
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'temp/kfchvCyHmsc.mp4':
Metadata:
major_brand : 3gp6
minor_version : 256
compatible_brands: isom3gp6
creation_time : 2015-03-26 09:22:44
Duration: 00:00:08.27, start: 0.000000, bitrate: 218 kb/s
Stream #0:0(und): Video: mpeg4 (Simple Profile) (mp4v / 0x7634706D), yuv420p, 320x180 [SAR 1:1 DAR 16:9], 187 kb/s, 23.98 fps, 23.98 tbr, 24k tbn, 24k tbc (default)
Metadata:
creation_time : 2015-03-26 09:22:44
handler_name : IsoMedia File Produced by Google, 5-11-2011
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 22050 Hz, mono, fltp, 31 kb/s (default)
Metadata:
creation_time : 2015-03-26 09:22:44
handler_name : IsoMedia File Produced by Google, 5-11-2011
[libx264 @ 0x2641fc0] using SAR=1/1
[libx264 @ 0x2641fc0] using cpu capabilities: MMX2 SSE2Fast SSSE3 SSE4.2 AVX FMA3 AVX2 LZCNT BMI2
[libx264 @ 0x2641fc0] profile High, level 1.2
[libx264 @ 0x2641fc0] 264 - core 148 r2643 5c65704 - H.264/MPEG-4 AVC codec - Copyleft 2003-2015 - http://www.videolan.org/x264.html - options: cabac=1 ref=3 deblock=1:0:0 analyse=0x3:0x113 me=hex subme=7 psy=1 psy_rd=1.00:0.00 mixed_ref=1 me_range=16 chroma_me=1 trellis=1 8x8dct=1 cqm=0 deadzone=21,11 fast_pskip=1 chroma_qp_offset=-2 threads=6 lookahead_threads=1 sliced_threads=0 nr=0 decimate=1 interlaced=0 bluray_compat=0 constrained_intra=0 bframes=3 b_pyramid=2 b_adapt=1 b_bias=0 direct=1 weightb=1 open_gop=0 weightp=2 keyint=250 keyint_min=23 scenecut=40 intra_refresh=0 rc_lookahead=40 rc=crf mbtree=1 crf=23.0 qcomp=0.60 qpmin=0 qpmax=69 qpstep=4 ip_ratio=1.40 aq=1:1.00
[aac @ 0x2642f00] The encoder 'aac' is experimental but experimental codecs are not enabled, add '-strict -2' if you want to use it.
To go into more detail this excerpt from your console output/log explains the reason why it failed:
[aac @ 0x2642f00] The encoder 'aac' is experimental but experimental codecs are not enabled, add '-strict -2' if you want to use it.
Your ffmpeg
was old, as you already found out. Using the outdated ffmpeg
would have required -strict -2
(or the alias -strict experimental
) to encode using the built-in FFmpeg AAC encoder, but your command was lacking this.
Eventually the AAC encoder was improved and the experimental status was removed. Using a recent version allows you to encode AAC without -strict
. See the FFmpeg Download page for links to already compiled recent builds of ffmpeg
for Linux, macOS, and Windows.
For more info see FFmpeg Wiki: AAC.