Skip to content

Commit

Permalink
fix: audio and subtitle merging error
Browse files Browse the repository at this point in the history
  • Loading branch information
ChetanXpro committed Aug 8, 2023
1 parent 57905e7 commit 49e1a86
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 65 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ dist
.env
new.mp4
basicaudio.mp3
basicaudio.wav
basicaudio.wav
basicaudio.wav.srt
shorts
15 changes: 8 additions & 7 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ const outputFilePath = path.join(__dirname, '..', 'basicaudio.wav')

const videoFilePath = path.join(__dirname, '..', 'new.mp4')

const outputVideoFilePath = path.join(__dirname, '..', 'ytshort.mp4')
const outputVideoFilePath = path.join(__dirname, '..', 'shorts', 'ytshort.mp4')

const generateYoutubeShort = async () => {
try {
const script = await createShortScript({ language: 'english', topic: 'historical fact' })
const script = await createShortScript({ language: 'english', topic: 'world war fact' })
console.log('SCRIPT GENERATED: ', script)

if (!script) throw new Error('Script not generated')
Expand All @@ -30,12 +30,13 @@ const generateYoutubeShort = async () => {

await whisper(outputFilePath)

console.log('TRANSCRIPT GENERATED')
console.log('MERGING AUDIO AND VIDEO')

await whisper(outputFilePath)
console.log('MERGING AUDIO...')

mergeAudio({ videoFilePath, audioFilePath: outputFilePath, outputVideoPath: outputVideoFilePath })
await mergeAudio({
videoFilePath,
audioFilePath: outputFilePath,
outputVideoPath: outputVideoFilePath,
})
} catch (error) {
console.log('Error in createShortScript: ', error)
}
Expand Down
1 change: 0 additions & 1 deletion src/transcript/transcribe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { nodewhisper } from 'nodejs-whisper'

export const whisper = async (filePath: string, options?: any) => {
try {
console.log('Transcribing', filePath)
const transcript = await nodewhisper(filePath, {
modelName: 'tiny.en',
whisperOptions: {
Expand Down
101 changes: 45 additions & 56 deletions src/video/video.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import ffmpeg from 'fluent-ffmpeg'
import fs from 'fs'

const videoFilePath = 'new.mp4' // Replace with your original video file path
import path from 'path'

export const mergeAudio = async ({
videoFilePath,
Expand All @@ -12,68 +11,58 @@ export const mergeAudio = async ({
audioFilePath: string
outputVideoPath: string
}) => {
fs.access(videoFilePath, fs.constants.F_OK, err => {
console.log(`${videoFilePath} ${err ? 'does not exist' : 'exists'}`)
})

fs.access(videoFilePath, fs.constants.F_OK, err => {
console.log(`${audioFilePath} ${err ? 'does not exist' : 'exists'}`)
})

fs.access(videoFilePath, fs.constants.F_OK, err => {
console.log(`${outputVideoPath} ${err ? 'does not exist' : 'exists'}`)
const videodata: any = await new Promise((resolve, reject) => {
ffmpeg.ffprobe(videoFilePath, (err, videoMetadata) => {
if (err) {
console.error('Error getting video duration:', err.message)
reject(err)
}
resolve(videoMetadata)
})
})

ffmpeg.ffprobe(videoFilePath, (err, videoMetadata) => {
if (err) {
console.error('Error getting video duration:', err.message)
return
}

const videoDurationInSeconds = videoMetadata.format.duration

const audiodata: any = await new Promise((resolve, reject) => {
ffmpeg.ffprobe(audioFilePath, (err, audioMetadata) => {
if (err) {
console.error('Error getting audio duration:', err.message)
return
reject(err)
}
resolve(audioMetadata)
})
})

// console.log('videodata: ', videodata)
// console.log('audiodata: ', audiodata)

const audioDurationInSeconds = audioMetadata.format.duration
const videoDurationInSeconds = videodata.format.duration

// Calculate how many times the audio needs to be repeated to match the video duration
const trimDuration = Math.min(videoDurationInSeconds!, audioDurationInSeconds!)
const audioSpeed = 1
const targetWidth = 1080
const targetHeight = 1920
const adjustedTrimDuration = trimDuration / audioSpeed
const videoFilter = `scale=${targetWidth}:-1,pad=${targetWidth}:${targetHeight}:(ow-iw)/2:(oh-ih)/2:black`
const audioFilter = `atempo=${audioSpeed},aformat=sample_rates=44100:channel_layouts=stereo`
const srtFilePath = 'basicaudio.wav.srt'
// Merge the audio with the video
ffmpeg(videoFilePath)
.inputOptions(`-t ${adjustedTrimDuration}`)
.input(audioFilePath)
const audioDurationInSeconds = audiodata.format.duration

.videoFilter(videoFilter)
.audioFilter(audioFilter)
.outputOptions([
'-vf',
`subtitles=${srtFilePath}`,
'-map',
'0:v',
'-map',
'1:a',
'-c:v libx264',
'-c:a aac',
])
.output(outputVideoPath)
.on('end', () => {
console.log('Audio added to video complete!')
})
.on('error', err => {
console.error('Error during audio adding to video:', err.message)
})
.run()
// Calculate how many times the audio needs to be repeated to match the video duration
const trimDuration = Math.min(videoDurationInSeconds!, audioDurationInSeconds!)
const audioSpeed = 1
const targetWidth = 1080
const targetHeight = 1920
const adjustedTrimDuration = trimDuration / audioSpeed
const videoFilter = `scale=${targetWidth}:-1,pad=${targetWidth}:${targetHeight}:(ow-iw)/2:(oh-ih)/2:black`
const audioFilter = `atempo=${audioSpeed},aformat=sample_rates=44100:channel_layouts=stereo`
const srtFilePath = 'basicaudio.wav.srt'
const newSrtFilePath = path.join(__dirname, '..', '..', srtFilePath)

// Merge the audio with the video
ffmpeg(videoFilePath)
.inputOptions(`-t ${adjustedTrimDuration}`)
.input(audioFilePath)

.videoFilter(videoFilter)
.audioFilter(audioFilter)
.outputOptions(['-vf', `subtitles=${newSrtFilePath}`, '-map', '0:v', '-map', '1:a', '-c:v libx264', '-c:a aac'])
.output(outputVideoPath)
.on('end', () => {
console.log('Audio added to video complete!')
})
})
.on('error', err => {
console.error('Error during audio adding to video:', err.message)
})
.run()
}

0 comments on commit 49e1a86

Please sign in to comment.