Skip to content

Commit

Permalink
fix: use yuv420p subsampling for best compatibility
Browse files Browse the repository at this point in the history
Fixes #26
  • Loading branch information
rprieto committed Nov 26, 2023
1 parent 8b79faf commit 4550365
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 11 deletions.
28 changes: 21 additions & 7 deletions lib/video/ffargs.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,8 @@ exports.prepare = function (source, target, options) {
args.push('-b:v', 0, '-crf', exports.crf(quality, encoder))
}

// AVCHD/MTS videos need a full-frame export to avoid interlacing artefacts
if (path.extname(source).toLowerCase() === '.mts') {
args.push('-vf', 'yadif=1')
} else if ((options.bitrate) && (options.hwaccel === 'vaapi')) {
// if VAAPI + here you to add the scaling option too ",scale_vaapi=1280:-1"
args.push('-vf', 'format=nv12|vaapi,hwupload')
}
const filters = exports.videoFilters(source, options)
args.push('-vf', filters)

// target filename
args.push(target)
Expand All @@ -85,3 +80,22 @@ exports.crf = function (percent, encoder) {
const inverted = ENCODER_CRF[encoder].max - proportion
return Math.floor(inverted)
}

// Configure video filters
exports.videoFilters = function (source, options) {
const filters = []
// AVCHD/MTS videos need a full-frame export to avoid interlacing artefacts
if (path.extname(source).toLowerCase() === '.mts') {
filters.push('yadif=1')
}
// Configure subsampling and hardware acceleration
if ((options.bitrate) && (options.hwaccel === 'vaapi')) {
// VAAPI requires nv12, which is equivalent to yuv420p for an h264 stream
// Here we could add scaling option too e.g. ",scale_vaapi=1280:-1"
filters.push('format=nv12|vaapi', 'hwupload')
} else {
// Standard case: use YUV420p which has the best compatibility
filters.push('format=yuv420p')
}
return filters.join(',')
}
30 changes: 26 additions & 4 deletions test/unit/ffargs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,32 @@ describe('ffargs', () => {
should(ffargs.crf(100, 'vpx')).eql(15)
})

it('handles MTS interlacing', () => {
const args = ffargs.prepare('source.mts', 'target.mp4', {})
const str = args.join(' ')
should(str).match(/-vf yadif=1/)
describe('video filters', () => {
it('uses yuv420p chroma subsampling by default', () => {
// videos from recent iPhones use yuv420p10le
// once converted to h264 they don't play well in browsers / macOS finder
// ffmpeg recommends using yuv420p for best compatibility
// see http://trac.ffmpeg.org/wiki/Encode/H.264
// and https://trac.ffmpeg.org/wiki/Encode/VP9
const vf = ffargs.videoFilters('source.mov', {})
should(vf).match(/format=yuv420p/)
})

it('handles MTS interlacing', () => {
const vf = ffargs.videoFilters('source.mts', {})
should(vf).match(/yadif=1,format=yuv420p/)
})

it('handles VAAPI hardware acceleration', () => {
const vf = ffargs.videoFilters('source.mov', { hwaccel: 'vaapi', bitrate: '1200k' })
should(vf).match(/format=nv12\|vaapi,hwupload/)
})

it('passes the video filter argument', () => {
const args = ffargs.prepare('source.mov', 'target.mp4', {})
const str = args.join(' ')
should(str).match(/-vf format=yuv420p/)
})
})

describe('framerate', () => {
Expand Down

0 comments on commit 4550365

Please sign in to comment.