jbilcke-hf HF staff commited on
Commit
74dba9a
·
1 Parent(s): d5d9687

fixed bugs

Browse files
package-lock.json CHANGED
@@ -2049,9 +2049,9 @@
2049
  }
2050
  },
2051
  "node_modules/get-tsconfig": {
2052
- "version": "4.7.4",
2053
- "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.4.tgz",
2054
- "integrity": "sha512-ofbkKj+0pjXjhejr007J/fLf+sW+8H7K5GCm+msC8q3IpvgjobpyPqSRFemNyIMxklC0zeJpi7VDFna19FacvQ==",
2055
  "dev": true,
2056
  "dependencies": {
2057
  "resolve-pkg-maps": "^1.0.0"
 
2049
  }
2050
  },
2051
  "node_modules/get-tsconfig": {
2052
+ "version": "4.7.5",
2053
+ "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.7.5.tgz",
2054
+ "integrity": "sha512-ZCuZCnlqNzjb4QprAzXKdpp/gh6KTxSJuw3IBsPnV/7fV4NxC9ckB+vPTt8w7fJA0TaSD7c55BR47JD6MEDyDw==",
2055
  "dev": true,
2056
  "dependencies": {
2057
  "resolve-pkg-maps": "^1.0.0"
src/bug-in-bun/aitube_ffmpeg/concatenate/concatenateAudio.ts CHANGED
@@ -86,7 +86,7 @@ export async function concatenateAudio({
86
  prevLabel
87
  })
88
  */
89
-
90
  let cmd: FfmpegCommand = ffmpeg() // .outputOptions('-vn');
91
 
92
  audioFilePaths.forEach((audio, i) => {
 
86
  prevLabel
87
  })
88
  */
89
+
90
  let cmd: FfmpegCommand = ffmpeg() // .outputOptions('-vn');
91
 
92
  audioFilePaths.forEach((audio, i) => {
src/bug-in-bun/aitube_ffmpeg/concatenate/concatenateVideosWithAudio.ts CHANGED
@@ -38,6 +38,7 @@ export const concatenateVideosWithAudio = async ({
38
  asBase64 = false,
39
  }: ConcatenateVideoWithAudioOptions): Promise<string> => {
40
 
 
41
  try {
42
  // Prepare temporary directories
43
  const tempDir = await getRandomDirectory()
@@ -113,6 +114,7 @@ export const concatenateVideosWithAudio = async ({
113
  '-map', '[a]',
114
  '-c:v', 'copy',
115
  '-c:a', 'aac',
 
116
  ]);
117
  } else {
118
  // console.log(`concatenateVideosWithAudio: case 2: additional audio was provided, but we don't already have audio: we overwrite`)
@@ -123,6 +125,7 @@ export const concatenateVideosWithAudio = async ({
123
  '-map', '1:a',
124
  '-c:v', 'copy',
125
  '-c:a', 'aac',
 
126
  ]);
127
  }
128
  } else {
@@ -135,7 +138,6 @@ export const concatenateVideosWithAudio = async ({
135
  ]);
136
  }
137
 
138
-
139
  /*
140
  console.log("concatenateVideosWithAudio: DEBUG:", {
141
  videoTracksVolume,
@@ -147,9 +149,9 @@ export const concatenateVideosWithAudio = async ({
147
  audioFilePath,
148
  // additionalAudioVolume,
149
  finalOutputFilePath
150
- })
151
- */
152
-
153
  // Set up event handlers for ffmpeg processing
154
  const promise = new Promise<string>((resolve, reject) => {
155
  ffmpegCommand.on('start', function(commandLine) {
 
38
  asBase64 = false,
39
  }: ConcatenateVideoWithAudioOptions): Promise<string> => {
40
 
41
+ console.log(`concatenateVideosWithAudio()`)
42
  try {
43
  // Prepare temporary directories
44
  const tempDir = await getRandomDirectory()
 
114
  '-map', '[a]',
115
  '-c:v', 'copy',
116
  '-c:a', 'aac',
117
+ '-shortest'
118
  ]);
119
  } else {
120
  // console.log(`concatenateVideosWithAudio: case 2: additional audio was provided, but we don't already have audio: we overwrite`)
 
125
  '-map', '1:a',
126
  '-c:v', 'copy',
127
  '-c:a', 'aac',
128
+ '-shortest'
129
  ]);
130
  }
131
  } else {
 
138
  ]);
139
  }
140
 
 
141
  /*
142
  console.log("concatenateVideosWithAudio: DEBUG:", {
143
  videoTracksVolume,
 
149
  audioFilePath,
150
  // additionalAudioVolume,
151
  finalOutputFilePath
152
+ })
153
+ */
154
+
155
  // Set up event handlers for ffmpeg processing
156
  const promise = new Promise<string>((resolve, reject) => {
157
  ffmpegCommand.on('start', function(commandLine) {
src/bug-in-bun/aitube_ffmpeg/overlay/htmlToBase64Png.ts CHANGED
@@ -30,11 +30,22 @@ export async function htmlToBase64Png({
30
  const browser = await puppeteer.launch({
31
  headless: true,
32
 
 
 
 
 
 
 
33
  // apparently we need those, see:
34
  // https://unix.stackexchange.com/questions/694734/puppeteer-in-alpine-docker-with-chromium-headless-dosent-seems-to-work
35
- executablePath: '/usr/bin/chromium-browser',
 
 
 
 
 
36
  args: [
37
- '--no-sandbox',
38
  '--headless',
39
  '--disable-gpu',
40
  '--disable-dev-shm-usage'
 
30
  const browser = await puppeteer.launch({
31
  headless: true,
32
 
33
+ // for macOS do this (yeah.. with the "no quarantine"..)
34
+ // brew install chromium --no-quarantine
35
+ // and:
36
+ // which chromium
37
+ // to detect where the executable path is
38
+
39
  // apparently we need those, see:
40
  // https://unix.stackexchange.com/questions/694734/puppeteer-in-alpine-docker-with-chromium-headless-dosent-seems-to-work
41
+ // https://stackoverflow.com/questions/59979188/error-failed-to-launch-the-browser-process-puppeteer
42
+ executablePath:
43
+ os.type() === "Darwin"
44
+ ? '/opt/homebrew/bin/chromium'
45
+ : '/usr/bin/chromium-browser',
46
+
47
  args: [
48
+ '--no-sandbox', // for alpine
49
  '--headless',
50
  '--disable-gpu',
51
  '--disable-dev-shm-usage'
src/core/exporters/storyboardSegmentToVideoFile.ts CHANGED
@@ -41,21 +41,30 @@ export async function storyboardSegmentToVideoFile({
41
  const interfaceSegment = interfaceSegments.at(0)
42
  if (interfaceSegment) {
43
  // here we are free to use mp4, since this is an internal intermediary format
44
- const videoSegmentWithOverlayFilePath = join(outputDir, `tmp_asset_${segment.id}_with_interface.mp4`)
45
-
46
- await addTextToVideo({
47
- inputVideoPath: storyboardSegmentVideoFilePath,
48
- outputVideoPath: videoSegmentWithOverlayFilePath,
49
- text: interfaceSegment.assetUrl.startsWith("data:text/")
50
- ? atob(extractBase64(interfaceSegment.assetUrl).data)
51
- : interfaceSegment.assetUrl,
52
- width: clap.meta.width,
53
- height: clap.meta.height,
54
- })
55
-
56
- // we overwrite
57
- await deleteFile(storyboardSegmentVideoFilePath)
58
- storyboardSegmentVideoFilePath = videoSegmentWithOverlayFilePath
 
 
 
 
 
 
 
 
 
59
  }
60
 
61
  const dialogueSegments = filterSegments(
 
41
  const interfaceSegment = interfaceSegments.at(0)
42
  if (interfaceSegment) {
43
  // here we are free to use mp4, since this is an internal intermediary format
44
+ let videoSegmentWithOverlayFilePath = join(outputDir, `tmp_asset_${segment.id}_with_interface.mp4`)
45
+
46
+ let success = false
47
+ // this can fail due to puppeteer
48
+ try {
49
+ await addTextToVideo({
50
+ inputVideoPath: storyboardSegmentVideoFilePath,
51
+ outputVideoPath: videoSegmentWithOverlayFilePath,
52
+ text: interfaceSegment.assetUrl.startsWith("data:text/")
53
+ ? atob(extractBase64(interfaceSegment.assetUrl).data)
54
+ : interfaceSegment.assetUrl,
55
+ width: clap.meta.width,
56
+ height: clap.meta.height,
57
+ })
58
+ success = true
59
+ } catch (err) {
60
+ console.error(`failed to add text to the video: ${err}`)
61
+ success = false
62
+ }
63
+ if (success) {
64
+ // we overwrite
65
+ await deleteFile(storyboardSegmentVideoFilePath)
66
+ storyboardSegmentVideoFilePath = videoSegmentWithOverlayFilePath
67
+ }
68
  }
69
 
70
  const dialogueSegments = filterSegments(
src/index.ts CHANGED
@@ -82,7 +82,7 @@ app.post("/", async (req, res) => {
82
  res.download(outputFilePath, async () => {
83
  // clean-up after ourselves (we clear the whole tmp directory)
84
  await deleteFile(tmpWorkDir)
85
- console.log("cleared the temporary folder")
86
  })
87
  return
88
  } catch (err) {
 
82
  res.download(outputFilePath, async () => {
83
  // clean-up after ourselves (we clear the whole tmp directory)
84
  await deleteFile(tmpWorkDir)
85
+ // console.log("cleared the temporary folder")
86
  })
87
  return
88
  } catch (err) {
src/main.ts CHANGED
@@ -41,6 +41,7 @@ export async function clapToTmpVideoFilePath({
41
  tmpWorkDir: string
42
  outputFilePath: string
43
  }> {
 
44
 
45
  // in case we have an issue with the format
46
  if (format !== "mp4" && format !== "webm") {
@@ -104,7 +105,7 @@ export async function clapToTmpVideoFilePath({
104
 
105
  console.log(`clapToTmpVideoFilePath: concatenatedVideosNoMusic`, concatenatedVideosNoMusic)
106
 
107
- const audioTracks: string[] = []
108
 
109
  const musicSegments = clap.segments.filter(s =>
110
  s.category === ClapSegmentCategory.MUSIC &&
@@ -137,56 +138,67 @@ export async function clapToTmpVideoFilePath({
137
  continue
138
  }
139
 
140
- const newTrackFileName = await writeBase64ToFile(
141
  segment.assetUrl,
142
  join(outputDir, `tmp_asset_${segment.id}.${analysis.extension}`)
143
  )
144
 
145
- audioTracks.push(newTrackFileName)
 
146
 
147
  availableMusicDurationInMs += durationInMs
148
  }
149
 
150
  let concatenatedAudio: ConcatenateAudioOutput | undefined = undefined
151
 
152
- if (audioTracks.length > 0) {
153
- console.log(`clapToTmpVideoFilePath: calling concatenateAudio over ${audioTracks.length} audio tracks`)
154
 
155
  if (!detectedMusicTrackFormat) {
156
  throw new Error(`uh that's weird, we couldn't detect the audio type`)
157
  }
158
 
159
- const availableMusicTracks = [...audioTracks]
160
 
161
  // if we don't have enough music audio content
162
  while (availableMusicDurationInMs < totalDurationInMs) {
163
- let trackToUse = availableMusicTracks.shift()
164
 
165
  // abort if there are no available tracks (for some reason)
166
- if (!trackToUse) { break }
167
 
168
- availableMusicTracks.push(trackToUse)
169
 
170
  // we artificially duplicate it (note: this will be cross-faded)
171
- const { durationInMs } = await getMediaInfo(trackToUse)
172
 
173
  // let's abord if we have bad data
174
  if (!durationInMs || durationInMs < 1000) { break }
175
 
176
- audioTracks.push(trackToUse)
177
 
178
  availableMusicDurationInMs += durationInMs
179
  }
180
 
 
 
 
 
 
 
 
 
 
181
  concatenatedAudio = await concatenateAudio({
182
  output: join(outputDir, `tmp_asset_concatenated_audio.${detectedMusicTrackFormat}`),
183
- audioTracks,
184
  crossfadeDurationInSec: 2, // 2 seconds
185
  outputFormat: detectedMusicTrackFormat
186
  })
187
- console.log(`clapToTmpVideoFilePath: concatenatedAudio = ${concatenatedAudio}`)
188
  }
189
 
 
190
  console.log(`calling concatenateVideosWithAudio: `, {
191
  output: join(outputDir, `final_video.${format}`),
192
  format,
@@ -196,6 +208,7 @@ export async function clapToTmpVideoFilePath({
196
  videoTracksVolume: concatenatedAudio ? 0.85 : 1.0,
197
  audioTrackVolume: concatenatedAudio ? 0.15 : 0.0, // let's keep the music volume low
198
  })
 
199
 
200
  const finalFilePathOfVideoWithMusic = await concatenateVideosWithAudio({
201
  output: join(outputDir, `final_video.${format}`),
@@ -211,14 +224,16 @@ export async function clapToTmpVideoFilePath({
211
 
212
  if (clearTmpFilesAtEnd) {
213
  // we delete all the temporary assets
214
- console.log(`clapToTmpVideoFilePath: calling deleteFilesWithName(${outputDir}, 'tmp_asset_')`)
215
  await deleteFilesWithName(outputDir, `tmp_asset_`)
216
  }
217
 
 
218
  console.log(`clapToTmpVideoFilePath: returning ${JSON.stringify( {
219
  tmpWorkDir: outputDir,
220
  outputFilePath: finalFilePathOfVideoWithMusic
221
  }, null, 2)}`)
 
222
 
223
  return {
224
  tmpWorkDir: outputDir,
 
41
  tmpWorkDir: string
42
  outputFilePath: string
43
  }> {
44
+ console.log(`clapToTmpVideoFilePath()`)
45
 
46
  // in case we have an issue with the format
47
  if (format !== "mp4" && format !== "webm") {
 
105
 
106
  console.log(`clapToTmpVideoFilePath: concatenatedVideosNoMusic`, concatenatedVideosNoMusic)
107
 
108
+ const musicFilePaths: string[] = []
109
 
110
  const musicSegments = clap.segments.filter(s =>
111
  s.category === ClapSegmentCategory.MUSIC &&
 
138
  continue
139
  }
140
 
141
+ const newMusicFilePath = await writeBase64ToFile(
142
  segment.assetUrl,
143
  join(outputDir, `tmp_asset_${segment.id}.${analysis.extension}`)
144
  )
145
 
146
+ // console.log("wrote music to " + newMusicFilePath)
147
+ musicFilePaths.push(newMusicFilePath)
148
 
149
  availableMusicDurationInMs += durationInMs
150
  }
151
 
152
  let concatenatedAudio: ConcatenateAudioOutput | undefined = undefined
153
 
154
+ if (musicFilePaths.length > 0) {
155
+ // console.log(`clapToTmpVideoFilePath: calling concatenateAudio over ${musicFilePaths.length} audio tracks`)
156
 
157
  if (!detectedMusicTrackFormat) {
158
  throw new Error(`uh that's weird, we couldn't detect the audio type`)
159
  }
160
 
161
+ const availableMusicFilePaths = [...musicFilePaths]
162
 
163
  // if we don't have enough music audio content
164
  while (availableMusicDurationInMs < totalDurationInMs) {
165
+ let musicFilePathToRepeat = availableMusicFilePaths.shift()
166
 
167
  // abort if there are no available tracks (for some reason)
168
+ if (!musicFilePathToRepeat) { break }
169
 
170
+ availableMusicFilePaths.push(musicFilePathToRepeat)
171
 
172
  // we artificially duplicate it (note: this will be cross-faded)
173
+ const { durationInMs } = await getMediaInfo(musicFilePathToRepeat)
174
 
175
  // let's abord if we have bad data
176
  if (!durationInMs || durationInMs < 1000) { break }
177
 
178
+ musicFilePaths.push(musicFilePathToRepeat)
179
 
180
  availableMusicDurationInMs += durationInMs
181
  }
182
 
183
+ /*
184
+ console.log("DEBUG:", {
185
+ musicFilePaths,
186
+ availableMusicFilePaths,
187
+ availableMusicDurationInMs
188
+ })
189
+ */
190
+
191
+
192
  concatenatedAudio = await concatenateAudio({
193
  output: join(outputDir, `tmp_asset_concatenated_audio.${detectedMusicTrackFormat}`),
194
+ audioFilePaths: musicFilePaths,
195
  crossfadeDurationInSec: 2, // 2 seconds
196
  outputFormat: detectedMusicTrackFormat
197
  })
198
+ // console.log(`clapToTmpVideoFilePath: concatenatedAudio = ${concatenatedAudio}`)
199
  }
200
 
201
+ /*
202
  console.log(`calling concatenateVideosWithAudio: `, {
203
  output: join(outputDir, `final_video.${format}`),
204
  format,
 
208
  videoTracksVolume: concatenatedAudio ? 0.85 : 1.0,
209
  audioTrackVolume: concatenatedAudio ? 0.15 : 0.0, // let's keep the music volume low
210
  })
211
+ */
212
 
213
  const finalFilePathOfVideoWithMusic = await concatenateVideosWithAudio({
214
  output: join(outputDir, `final_video.${format}`),
 
224
 
225
  if (clearTmpFilesAtEnd) {
226
  // we delete all the temporary assets
227
+ // console.log(`clapToTmpVideoFilePath: calling deleteFilesWithName(${outputDir}, 'tmp_asset_')`)
228
  await deleteFilesWithName(outputDir, `tmp_asset_`)
229
  }
230
 
231
+ /*
232
  console.log(`clapToTmpVideoFilePath: returning ${JSON.stringify( {
233
  tmpWorkDir: outputDir,
234
  outputFilePath: finalFilePathOfVideoWithMusic
235
  }, null, 2)}`)
236
+ */
237
 
238
  return {
239
  tmpWorkDir: outputDir,