2018-10-06 12:30:02 +00:00
|
|
|
import {spawn} from 'child_process'
|
2019-01-25 15:00:35 +00:00
|
|
|
import ffmpeg from 'fluent-ffmpeg'
|
|
|
|
|
2018-10-06 12:30:02 +00:00
|
|
|
import path from 'path'
|
|
|
|
import asn from './async'
|
|
|
|
|
|
|
|
function parseTitle (data) {
|
|
|
|
let tt = data.title
|
|
|
|
|
|
|
|
// Remove []'s from the beginning
|
|
|
|
tt = tt.replace(/^\[\w+\]\s?/i, '')
|
|
|
|
|
|
|
|
// Remove "Official Video/Audio" tag
|
|
|
|
tt = tt.replace(/\s?(?:[\(\)\[\]])?Official\s?[\w]+(?:[\(\)\[\]])?/i, '')
|
|
|
|
|
|
|
|
// Remove "Audio" tag
|
|
|
|
tt = tt.replace(/\s?(?:[\(\)\[\]])Audio?(?:[\(\)\[\]])/i, '')
|
|
|
|
|
|
|
|
// Remove "lyrics" tag
|
|
|
|
tt = tt.replace(/\s?(?:[\(\)\[\]])?lyrics?\s?(?:[\w]+)?(?:[\(\)\[\]])?\s?/i, '')
|
|
|
|
|
|
|
|
// Artist / Title split
|
|
|
|
let at = tt.split(' - ', 2)
|
|
|
|
let artist
|
|
|
|
let title
|
|
|
|
|
|
|
|
if (at.length > 1) {
|
|
|
|
artist = at[0]
|
|
|
|
title = tt.substring(artist.length + 3)
|
|
|
|
} else {
|
|
|
|
artist = data.artist
|
|
|
|
title = tt
|
|
|
|
}
|
|
|
|
|
|
|
|
data.title = title
|
|
|
|
data.artist = artist
|
|
|
|
|
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
|
|
|
function getVideoInfo (arg) {
|
2019-11-04 20:51:10 +00:00
|
|
|
let yt = spawn('youtube-dl', ['--no-playlist', '-j', '-f', 'bestaudio/best', arg])
|
2018-10-06 12:30:02 +00:00
|
|
|
|
|
|
|
let output = ''
|
|
|
|
yt.stdout.on('data', function (chunk) {
|
|
|
|
output += chunk.toString('utf8')
|
|
|
|
})
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
|
|
yt.on('close', function () {
|
2019-11-04 20:51:10 +00:00
|
|
|
let ftdata = output.split('\n')
|
|
|
|
console.log(ftdata.length)
|
|
|
|
if (ftdata.length > 1) {
|
|
|
|
let composite = []
|
|
|
|
for (let i in ftdata) {
|
|
|
|
let dat
|
|
|
|
try {
|
|
|
|
dat = JSON.parse(ftdata[i])
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
delete dat.formats
|
|
|
|
composite.push(dat)
|
|
|
|
}
|
|
|
|
return resolve(composite)
|
|
|
|
}
|
|
|
|
|
2018-10-06 12:30:02 +00:00
|
|
|
let data = JSON.parse(output)
|
|
|
|
delete data.formats
|
|
|
|
resolve(data)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
function fetchVideo (data) {
|
|
|
|
return new Promise((resolve, reject) => {
|
2019-01-25 15:00:35 +00:00
|
|
|
let tempName = path.join(process.cwd(), `/tmp.yt.${data.id}.mp3`)
|
2019-01-26 22:35:09 +00:00
|
|
|
ffmpeg(data.url || data.file)
|
2019-01-25 15:00:35 +00:00
|
|
|
.audioCodec('libmp3lame')
|
|
|
|
.format('mp3')
|
|
|
|
.on('error', reject)
|
|
|
|
.on('end', function () {
|
2018-10-06 12:30:02 +00:00
|
|
|
resolve({
|
|
|
|
title: data.title,
|
|
|
|
artist: data.uploader,
|
|
|
|
url: data.webpage_url,
|
|
|
|
art: data.thumbnail,
|
|
|
|
source: tempName
|
|
|
|
})
|
|
|
|
})
|
2019-01-25 15:00:35 +00:00
|
|
|
.output(tempName)
|
|
|
|
.run()
|
2018-10-06 12:30:02 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
async function getInfos (file) {
|
2018-11-07 16:28:08 +00:00
|
|
|
let formatData = await asn.promiseExec(`ffprobe -i "${file}" -show_entries format -v quiet -of json`)
|
|
|
|
|
|
|
|
let parsed = JSON.parse(formatData.stdout)
|
2018-11-07 16:35:06 +00:00
|
|
|
if (!parsed || !parsed.format || !parsed.format.duration) throw new Error('Failed to parse metadata!')
|
2018-11-07 16:28:08 +00:00
|
|
|
parsed = parsed.format
|
2018-11-07 16:54:31 +00:00
|
|
|
|
2018-11-07 16:28:08 +00:00
|
|
|
let data = {
|
2018-11-07 16:41:40 +00:00
|
|
|
file,
|
2018-11-07 16:28:08 +00:00
|
|
|
duration: parseFloat(parsed.duration)
|
|
|
|
}
|
|
|
|
|
2018-11-07 16:54:31 +00:00
|
|
|
if (Math.floor(data.duration) === 0) throw new Error('Invalid file type!')
|
|
|
|
|
2018-11-07 16:28:08 +00:00
|
|
|
if (parsed.tags) {
|
|
|
|
for (let k in parsed.tags) {
|
|
|
|
let tagtype = k.toLowerCase()
|
|
|
|
let value = parsed.tags[k]
|
|
|
|
|
|
|
|
if (tagtype === 'date') tagtype = 'year'
|
2018-10-06 12:30:02 +00:00
|
|
|
if (tagtype === 'track' || tagtype === 'year') {
|
2018-11-07 16:28:08 +00:00
|
|
|
if (value.indexOf('/') !== -1) {
|
|
|
|
value = value.split('/')[0]
|
2018-10-06 12:30:02 +00:00
|
|
|
}
|
|
|
|
|
2018-11-07 16:28:08 +00:00
|
|
|
value = parseInt(value)
|
2018-10-06 12:30:02 +00:00
|
|
|
}
|
|
|
|
|
2018-11-07 16:28:08 +00:00
|
|
|
data[tagtype] = value
|
2018-10-06 12:30:02 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!data.title) {
|
|
|
|
let parsed = path.parse(file)
|
|
|
|
data.title = parsed.name
|
|
|
|
}
|
|
|
|
|
|
|
|
return data
|
|
|
|
}
|
|
|
|
|
|
|
|
export default {parseTitle, getVideoInfo, fetchVideo, getInfos}
|