Skip to content

Commit a1c773d

Browse files
committed
Allow odd multitrack audio
1 parent 7cd29fa commit a1c773d

File tree

2 files changed

+55
-21
lines changed

2 files changed

+55
-21
lines changed

services/vidispine/export.go

Lines changed: 49 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,9 @@ type ExportData struct {
6666
OriginalLanguage string
6767

6868
TranscribedLanguage string
69+
70+
// Warnings contains non-fatal issues encountered during export data preparation
71+
Warnings []string
6972
}
7073

7174
type ExportAudioSource enum.Member[string]
@@ -212,22 +215,40 @@ func enrichClipWithRelatedAudios(client Client, clip *Clip, oLanguagesToExport [
212215
// enrichClipWithEmbeddedAudio modifies the clip in-place with embedded audio
213216
//
214217
// TODO: return audiofiles instead of modifying original
215-
func enrichClipWithEmbeddedAudio(client Client, clip *Clip, languagesToExport []string) error {
218+
func enrichClipWithEmbeddedAudio(client Client, clip *Clip, languagesToExport []string) ([]string, error) {
216219
shapes, err := client.GetShapes(clip.VXID)
217220
if err != nil {
218-
return err
221+
return nil, err
219222
}
220223

221224
shape := shapes.GetShape("original")
225+
var warnings []string
226+
227+
// Handle unexpected audio component counts by falling back to first 2 tracks
228+
if len(shape.AudioComponent) > 2 && len(shape.AudioComponent) != 8 && len(shape.AudioComponent) != 16 {
229+
warnings = append(warnings, fmt.Sprintf(
230+
"Found %d audio components on item %s. Using first 2 tracks as Norwegian L+R for all languages.",
231+
len(shape.AudioComponent), clip.VXID))
222232

223-
if len(shape.AudioComponent) != 16 && len(shape.AudioComponent) != 8 && len(shape.AudioComponent) > 2 {
224-
return fmt.Errorf("found %d audio components, expected 1, 2 or 16 on item %s", len(shape.AudioComponent), clip.VXID)
233+
streams := []AudioStream{
234+
{StreamID: uint(shape.AudioComponent[0].EssenceStreamID), ChannelID: 0},
235+
{StreamID: uint(shape.AudioComponent[1].EssenceStreamID), ChannelID: 0},
236+
}
237+
238+
for _, lang := range languagesToExport {
239+
clip.AudioFiles[lang] = &AudioFile{
240+
VXID: clip.VXID,
241+
File: shape.GetPath(),
242+
Streams: streams,
243+
}
244+
}
245+
return warnings, nil
225246
}
226247

227248
if len(shape.AudioComponent) == 0 {
228249
// We have no audio, so we fall back to silence
229250
streams := []AudioStream{
230-
AudioStream{
251+
{
231252
ChannelID: 0,
232253
StreamID: 0,
233254
},
@@ -239,7 +260,7 @@ func enrichClipWithEmbeddedAudio(client Client, clip *Clip, languagesToExport []
239260
}
240261
}
241262

242-
return nil
263+
return nil, nil
243264
}
244265

245266
if len(shape.AudioComponent) == 1 && shape.AudioComponent[0].ChannelCount == 64 {
@@ -250,28 +271,28 @@ func enrichClipWithEmbeddedAudio(client Client, clip *Clip, languagesToExport []
250271
clip.AudioFiles[lang] = &AudioFile{
251272
File: shape.GetPath(),
252273
Streams: []AudioStream{
253-
AudioStream{
274+
{
254275
StreamID: 2,
255276
ChannelID: uint(langInfo.SoftronStartCh),
256277
},
257-
AudioStream{
278+
{
258279
StreamID: 2,
259280
ChannelID: uint(langInfo.SoftronStartCh) + 1,
260281
},
261282
},
262283
}
263284
} else {
264-
return fmt.Errorf("unknown language %s", lang)
285+
return nil, fmt.Errorf("unknown language %s", lang)
265286
}
266287
}
267288

268-
return nil
289+
return nil, nil
269290
}
270291

271292
if len(shape.AudioComponent) == 1 {
272293
// We have stereo or mono audio, so we copy it to all languages
273294
for _, lang := range languagesToExport {
274-
streams := []AudioStream{}
295+
var streams []AudioStream
275296
for i := 0; shape.AudioComponent[0].ChannelCount > i; i++ {
276297
streams = append(streams, AudioStream{
277298
StreamID: uint(shape.AudioComponent[0].EssenceStreamID),
@@ -286,14 +307,14 @@ func enrichClipWithEmbeddedAudio(client Client, clip *Clip, languagesToExport []
286307
}
287308
}
288309

289-
return nil
310+
return nil, nil
290311
}
291312

292313
if len(shape.AudioComponent) == 2 {
293314
var streams []AudioStream
294315
for _, c := range shape.AudioComponent {
295316
if c.ChannelCount != 1 {
296-
return fmt.Errorf("found %d channels in audio component, expected 1", c.ChannelCount)
317+
return nil, fmt.Errorf("found %d channels in audio component, expected 1", c.ChannelCount)
297318
}
298319
streams = append(streams, AudioStream{
299320
StreamID: uint(c.EssenceStreamID),
@@ -308,17 +329,22 @@ func enrichClipWithEmbeddedAudio(client Client, clip *Clip, languagesToExport []
308329
Streams: streams,
309330
}
310331
}
332+
return nil, nil
311333
}
312334

313335
if len(shape.AudioComponent) == 8 {
336+
// When there are 8 audio components but multiple languages requested,
337+
// fall back to using first 2 tracks as Norwegian L+R for all languages
314338
if len(languagesToExport) > 1 {
315-
return fmt.Errorf("found 8 audio components, expected 16")
339+
warnings = append(warnings, fmt.Sprintf(
340+
"Found 8 audio components on item %s but %d languages requested. Using first 2 tracks as Norwegian L+R for all languages.",
341+
clip.VXID, len(languagesToExport)))
316342
}
317343

318344
var streams []AudioStream
319345
for _, c := range shape.AudioComponent[:2] {
320346
if c.ChannelCount != 1 {
321-
return fmt.Errorf("found %d channels in audio component, expected 1", c.ChannelCount)
347+
return nil, fmt.Errorf("found %d channels in audio component, expected 1", c.ChannelCount)
322348
}
323349

324350
streams = append(streams, AudioStream{
@@ -334,12 +360,12 @@ func enrichClipWithEmbeddedAudio(client Client, clip *Clip, languagesToExport []
334360
Streams: streams,
335361
}
336362
}
363+
return warnings, nil
337364
}
338365

366+
// We have an actual 16 channel audio file, so we need to figure out which channels to use
367+
// and assign them to the correct language
339368
for _, lang := range languagesToExport {
340-
// We have an actual 16 channel audio file, so we need to figure out which channels to use
341-
// and assign them to the correct language
342-
343369
if l, ok := bccmflows.LanguagesByISO[lang]; ok {
344370
var streams []AudioStream
345371
for i := 0; i < l.MU1ChannelCount; i++ {
@@ -355,11 +381,11 @@ func enrichClipWithEmbeddedAudio(client Client, clip *Clip, languagesToExport []
355381
Streams: streams,
356382
}
357383
} else if lang != "" {
358-
return errors.New("No language " + lang + " found in bccmflows.LanguagesByISO")
384+
return nil, errors.New("No language " + lang + " found in bccmflows.LanguagesByISO")
359385
}
360386
}
361387

362-
return nil
388+
return nil, nil
363389
}
364390

365391
// GetSubclipNames returns the names of all the subclips
@@ -492,7 +518,9 @@ func GetDataForExport(client Client, itemVXID string, languagesToExport []string
492518
if *audioSource == ExportAudioSourceRelated {
493519
err = enrichClipWithRelatedAudios(client, clip, languagesToExport)
494520
} else if *audioSource == ExportAudioSourceEmbedded {
495-
err = enrichClipWithEmbeddedAudio(client, clip, languagesToExport)
521+
var clipWarnings []string
522+
clipWarnings, err = enrichClipWithEmbeddedAudio(client, clip, languagesToExport)
523+
out.Warnings = append(out.Warnings, clipWarnings...)
496524
}
497525

498526
if err != nil {

workflows/export/vx_export.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@ func VXExport(ctx workflow.Context, params VXExportParams) ([]wfutils.ResultOrEr
105105
return nil, err
106106
}
107107

108+
// Send warnings to Telegram
109+
for _, warning := range data.Warnings {
110+
wfutils.SendTelegramText(ctx, telegramChat,
111+
fmt.Sprintf("Warning during export of `%s`:\n%s", params.VXID, warning))
112+
}
113+
108114
if len(data.Clips) == 0 {
109115
wfutils.SendTelegramText(ctx, telegramChat,
110116
fmt.Sprintf("No clips found for `%s`.\nTitle: `%s`\nDestinations: `%s`\n\nRunID: `%s`",

0 commit comments

Comments
 (0)