Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updated audio and video codecs, and added hdr and container keywords. #1

Open
wants to merge 13 commits into
base: master
Choose a base branch
from
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ Parse names of video files to identify quality (e.g. 1080p), season/episode, yea
var parseVideo = require("video-name-parser");
parseVideo("south park s01e01.avi"); // { name: "south park", season: 1, episode: [1], type: "series", tag: [] }
parseVideo("south park s01e01e02.avi"); // { name: "south park", season: 1, episode: [1,2], type: "series", tag: [] }
parseVideo("The.Wizard.of.Oz.1939.1080p.BrRip.x264.mp4"); // { name: "wizard of oz", year: 1939, type: "movie", tag: [ "hd", "1080p" ] }
parseVideo("The.Wizard.of.Oz.1939.1080p.BrRip.x264.mp4"); // { name: "the wizard of oz", year: 1939, type: "movie", tag: [ "hd", "1080p" ] }
parseVideo("The.Wizard.of.Oz.1939.1080p.BrRip.x264.mp4", { extra: true }); // { ... extra: { resolution: ["1080p"], audio: [], codec: ["x264"], lowQualitySrc: [], highQualitySrc: ["brrip"] } }
parseVideo("something else.mp4"); // { name: "other" } // no year or season/ep found, assuming 'other'
parseVideo("something else.mp4"); // { type: "other" } // no year or season/ep found, assuming 'other'
```

## Returned properties
Expand All @@ -26,10 +26,12 @@ parseVideo("something else.mp4"); // { name: "other" } // no year or season/ep f
**extra** - optional ```{ extra: true }```
```
{
resolution: [ '1080p' ],
audio: ['dts-hd'],
codec: [ 'x264' ],
resolution: ['1080p'],
audioCodec: ['dts-hd'],
videoCodec: ['x264'],
hdr: ['10bit'],
lowQualitySrc: [],
highQualitySrc: [ 'brrip' ]
highQualitySrc: ['brrip'],
container: ['mkv']
}
```
```
186 changes: 98 additions & 88 deletions extra.js
Original file line number Diff line number Diff line change
@@ -1,88 +1,98 @@
'use strict '

var {
keywordType,
resolutionKeywords,
codecKeywords,
audioKeywords,
lowQualityReleaseKeywords,
highQualityReleaseKeywords,
allKeywords
} = require('./keywords')

// chars without escaping: [](). -;,_/\+
var separatorChars = '([\\[\\](). \\-;,_\\/\\\\+])'
// NOTE: Needs node ^8.10.0 V8 > 6.2 to work with lookbehind ?<=
var leftBoundary = '(^|(?<=' + separatorChars + '{1}))'
var rightBoundary = '((?=' + separatorChars + '{1})|$)'

var allKeywordsPattern = '(' + allKeywords.join('|') + ')'
var allKeywordsRegEx = new RegExp(leftBoundary + allKeywordsPattern + rightBoundary, 'gi')

var keywordsWithType = (function () {
var allKeywordsObj = {}

function addToAllKeywords(arr, type) {
return arr.forEach(element => {
allKeywordsObj[element] = type
})
}

addToAllKeywords(resolutionKeywords, keywordType.resolution)
addToAllKeywords(codecKeywords, keywordType.codec)
addToAllKeywords(audioKeywords, keywordType.audio)
addToAllKeywords(lowQualityReleaseKeywords, keywordType.lowQualitySrc)
addToAllKeywords(highQualityReleaseKeywords, keywordType.highQualitySrc)

return allKeywordsObj
}())

function pushUniqueToArray(arr, val) {
if (arr.indexOf(val) < 0) {
arr.push(val)
}
}

function getExtra(filePath) {
var extraData = { resolution: [], audio: [], codec: [], lowQualitySrc: [], highQualitySrc: [], }

if (!filePath
|| (typeof filePath !== 'string')) {
return extraData
}

var match = filePath.match(allKeywordsRegEx)

if (match)
match.reduce(function (extra, m) {
m = m.toLowerCase()
switch (keywordsWithType[m]) {
case keywordType.resolution:
pushUniqueToArray(extra.resolution, m)
break;
case keywordType.audio:
pushUniqueToArray(extra.audio, m)
break;
case keywordType.codec:
pushUniqueToArray(extra.codec, m)
break;
case keywordType.lowQualitySrc:
pushUniqueToArray(extra.lowQualitySrc, m)
break;
case keywordType.highQualitySrc:
pushUniqueToArray(extra.highQualitySrc, m)
break;
default:
break;
}

return extra

}, extraData)

return extraData
}

module.exports = {
getExtra: getExtra
}
'use strict '

var {
keywordType,
resolutionKeywords,
audioCodecKeywords,
videoCodecKeywords,
hdrKeywords,
lowQualityReleaseKeywords,
highQualityReleaseKeywords,
containerKeywords,
allKeywords
} = require('./keywords')

// chars without escaping: [](). -;,_/\+
var separatorChars = '([\\[\\](). \\-;,_\\/\\\\+])'
// NOTE: Needs node ^8.10.0 V8 > 6.2 to work with lookbehind ?<=
var leftBoundary = '(^|(?<=' + separatorChars + '{1}))'
var rightBoundary = '((?=' + separatorChars + '{1})|$)'

var allKeywordsPattern = '(' + allKeywords.join('|') + ')'
var allKeywordsRegEx = new RegExp(leftBoundary + allKeywordsPattern + rightBoundary, 'gi')

var keywordsWithType = (function () {
var allKeywordsObj = {}

function addToAllKeywords(arr, type) {
return arr.forEach(element => {
allKeywordsObj[element] = type
})
}

addToAllKeywords(resolutionKeywords, keywordType.resolution)
addToAllKeywords(audioCodecKeywords, keywordType.audioCodec)
addToAllKeywords(videoCodecKeywords, keywordType.videoCodec)
addToAllKeywords(hdrKeywords, keywordType.hdr)
addToAllKeywords(lowQualityReleaseKeywords, keywordType.lowQualitySrc)
addToAllKeywords(highQualityReleaseKeywords, keywordType.highQualitySrc)
addToAllKeywords(containerKeywords, keywordType.container)

return allKeywordsObj
}())

function pushUniqueToArray(arr, val) {
if (arr.indexOf(val) < 0) {
arr.push(val)
}
}

function getExtra(filePath) {
var extraData = { resolution: [], audioCodec: [], videoCodec: [], hdr: [], lowQualitySrc: [], highQualitySrc: [], container: []}

if (!filePath
|| (typeof filePath !== 'string')) {
return extraData
}

var match = filePath.match(allKeywordsRegEx)

if (match)
match.reduce(function (extra, m) {
m = m.toLowerCase()
switch (keywordsWithType[m]) {
case keywordType.resolution:
pushUniqueToArray(extra.resolution, m)
break;
case keywordType.audioCodec:
pushUniqueToArray(extra.audioCodec, m)
break;
case keywordType.videoCodec:
pushUniqueToArray(extra.videoCodec, m)
break;
case keywordType.hdr:
pushUniqueToArray(extra.hdr, m)
break;
case keywordType.lowQualitySrc:
pushUniqueToArray(extra.lowQualitySrc, m)
break;
case keywordType.highQualitySrc:
pushUniqueToArray(extra.highQualitySrc, m)
break;
case keywordType.container:
pushUniqueToArray(extra.container, m)
break;
default:
break;
}

return extra

}, extraData)

return extraData
}

module.exports = {
getExtra: getExtra
}
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ function parseVideoName(filePath, options)
meta.season = parseInt(seasonMatch[1], 10);

/* TODO: consider the case when a hyphen is used for multiple episodes ; e.g. e1-3 */
var episodeMatch = x.match(/E(\d{2})/ig);
var episodeMatch = x.match(/(?<=\W|\d)E(\d{2})/ig);
if (episodeMatch)
meta.episode = episodeMatch.map(function(y) { return parseInt(y.slice(1), 10) });

Expand Down
75 changes: 40 additions & 35 deletions keywords.js
Original file line number Diff line number Diff line change
@@ -1,35 +1,40 @@
'use strict '

var keywordType = {
none: 0,
resolution: 1,
audio: 2,
codec: 3,
lowQualitySrc: 4,
highQualitySrc: 5,
}

var resolutionKeywords = ['1080p', '1080i', '1920x1080', '720p', '720i', '480p', '480i', '1440p', '1440i', '2k', '2160p', '2160i', '3840x2160', '4k'];

var codecKeywords = ['divx', 'xvid', 'x264', 'x265', 'h264', 'hevc', 'avchd'];

var audioKeywords = ['dts', 'dts-hd', 'acc', 'aac2.0', 'aac 2.0', 'mp3', 'wav', 'truehd', 'ac3', 'ac-3', 'atmos', 'dtsma', 'dolby', 'dolbydigital', 'dolby-digital', 'eac3'];

var lowQualityReleaseKeywords = ['camrip', 'cam', 'ts', 'hdts', 'telesync', 'pdvd', 'predvdrip', 'wp', 'workprint', 'tc', 'hdtc', 'telecine',
'src', 'screener', 'dvdscr', 'dvdscreener', 'bdscr', 'ddc', 'r5'];

var highQualityReleaseKeywords = ['ppv', 'ppvrip', 'dvdrip', 'dvdmux', 'dvdr', 'dvd-full', 'full-rip', 'iso rip', 'lossless rip', 'untouched rip', 'dvd-5', 'dvd-9', 'dsr',
'dsrip', 'satrip', 'dthrip', 'dvbrip', 'hdtv', 'pdtv', 'dtvrip', 'tvrip', 'hdtvrip', 'vodrip', 'vodr', 'webdl', 'web dl', 'web-dl', 'web', 'hdrip', 'web-dlrip', 'webrip',
'web-cap', 'webcap', 'web cap', 'blu-ray', 'bluray', 'bdrip', 'bdrip', 'brrip', 'bdmv', 'bdr', 'bd25', 'bd50', 'bd5', 'bd9', 'ultrahd', 'remux'];

var allKeywords = resolutionKeywords.concat(codecKeywords).concat(audioKeywords).concat(lowQualityReleaseKeywords).concat(highQualityReleaseKeywords)

module.exports = {
keywordType: keywordType,
resolutionKeywords: resolutionKeywords,
codecKeywords: codecKeywords,
audioKeywords: audioKeywords,
lowQualityReleaseKeywords: lowQualityReleaseKeywords,
highQualityReleaseKeywords: highQualityReleaseKeywords,
allKeywords: allKeywords
}
'use strict '

var keywordType = {
none: 0,
resolution: 1,
audioCodec: 2,
videoCodec: 3,
lowQualitySrc: 4,
highQualitySrc: 5,
hdr: 6,
container: 7,
}

var resolutionKeywords = ['1080p', '1080i', '1920x1080', '720p', '720i', '480p', '480i', '1440p', '1440i', '2k', '2160p', '2160i', '3840x2160', '4k'];

var audioCodecKeywords = ['dts', 'dts-hd', 'acc', 'aac2.0', 'aac 2.0', 'mp3', 'wav', 'truehd', 'ac3', 'ac-3', 'atmos', 'dtsma', 'dolby', 'dolbydigital', 'dolby-digital', 'eac3', '6ch', 'dd5.1', 'dd 5.1', 'ddp5.1','ddp 5.1', 'aac5.1', 'aac 5.1'];

var videoCodecKeywords = ['divx', 'xvid', 'rv10', 'rv13', 'rv20', 'rv30', 'rv40', 'mpeg', 'mpeg2', 'mpeg-2', 'mpg2', 'h262', 'h.262', 'x262', 'xmpeg2', 'mpeg2x', 'mpeg4', 'h263', 'h.263', 'x263', 'h264', 'h.264', 'x264', 'h265', 'h.265', 'x265', 'hevc', 'avchd', 'av1'];

var hdrKeywords = ['hdr', 'hdr10plus', '10bit', '10bits', 'hevc10', 'yuv420p10']

var lowQualityReleaseKeywords = ['camrip', 'cam', 'hqcam', 'ts', 'hdts', 'telesync', 'pdvd', 'predvdrip', 'wp', 'workprint', 'tc', 'hdtc', 'telecine', 'src', 'screener', 'dvdscr', 'dvdscreener', 'bdscr', 'ddc', 'r5', 'vhs', 'vhsrip'];

var highQualityReleaseKeywords = ['ppv', 'ppvrip', 'dvdrip', 'dvdmux', 'dvdr', 'dvd-full', 'full-rip', 'iso rip', 'lossless rip', 'untouched rip', 'dvd-5', 'dvd-9', 'dsr', 'dsrip', 'satrip', 'dthrip', 'dvbrip', 'hdtv', 'pdtv', 'dtvrip', 'tvrip', 'hdtvrip', 'vodrip', 'vodr', 'webdl', 'web dl', 'web-dl', 'web', 'hdrip', 'web-dlrip', 'webrip', 'web-cap', 'webcap', 'web cap', 'blu-ray', 'bluray', 'bdrip', 'bdrip', 'brrip', 'bdmv', 'bdr', 'bd25', 'bd50', 'bd5', 'bd9', 'ultrahd', 'remux', 'uhd'];

var containerKeywords = ['mkv', 'mp4', 'avi']

var allKeywords = resolutionKeywords.concat(audioCodecKeywords).concat(videoCodecKeywords).concat(hdrKeywords).concat(lowQualityReleaseKeywords).concat(highQualityReleaseKeywords).concat(containerKeywords)

module.exports = {
keywordType: keywordType,
resolutionKeywords: resolutionKeywords,
audioCodecKeywords: audioCodecKeywords,
videoCodecKeywords: videoCodecKeywords,
hdrKeywords: hdrKeywords,
lowQualityReleaseKeywords: lowQualityReleaseKeywords,
highQualityReleaseKeywords: highQualityReleaseKeywords,
containerKeywords: containerKeywords,
allKeywords: allKeywords
}
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "video-name-parser",
"version": "2.0.0",
"version": "2.1.0",
"description": "Parse names of video files to identify quality (e.g. 1080p), season/episode, year, etc.",
"main": "index.js",
"scripts": {
Expand All @@ -16,7 +16,7 @@
"keywords": [
"parsing",
"video",
"naem"
"name"
],
"author": "Ivo Georgiev <[email protected]> (http://ivogeorgiev.com)",
"license": "MIT",
Expand Down