-
Notifications
You must be signed in to change notification settings - Fork 27
/
ingestfile
executable file
·734 lines (678 loc) · 30 KB
/
ingestfile
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
#!/bin/bash
# ingestfile
# select an audiovisual file, package it, and transcode it
VERSION="1.0"
QUEUEFILE="${HOME}/Desktop/queue.txt"
SCRIPTDIR=$(dirname "${0}")
. "${SCRIPTDIR}/mmfunctions" || { echo "Missing '${SCRIPTDIR}/mmfunctions'. Exiting." ; exit 1 ;};
_initialize_make
# assigns variables from temporary ingest file if present (for use with ingestfiletest)
if [ -f "${TEMP_INGEST}" ] ; then
INGESTLOG="${TEMP_INGEST}"
OP="$(_readingestlog "OPERATOR")"
INPUT="$(_readingestlog "INPUT")"
AUDIODECISION="$(_readingestlog "AUDIODECISION")"
CROPDECISION="$(_readingestlog "CROPDECISION")"
SLATE=$(_readingestlog "SLATE")
FORMULA="$(_readingestlog "AUDIODECISION")"
CLEANUPDECISION="$(_readingestlog "CLEANUPDECISION")"
PRIORITY="$(_readingestlog "PRIORITY")"
fi
# the mode associates the script with a particular set of microservices and options
# here the default mode is set which may be replaced with ingestfile options
MODE="default"
_usage(){
echo
echo "$(basename "${0}") ${VERSION}"
echo "This script will run an interactive interview and then process an input file accordingly."
echo "Dependencies: ${DEPENDENCIES[@]}"
echo "Usage: $(basename ${0}) [ -options ]"
echo " Default mode: presents a graphical user interface to specify file, media ID, and other options. Automatically creates broadcast and access copies, and delivers packages to ${OMNEONPATH}, ${PODCASTDELIVER}, ${YOUTUBEDELIVER}, and ${AIP_STORAGE}."
echo " -p Preservation mode: formula to be used when packaging digitized material and digitization logs. Creates access copies, but does not make any deliveries, and creates the package in the same directory as the input."
echo " -i PSA mode: formula to be used when packaging PSA files. Creates access copies, but does not make any deliveries except for sending the final package to ${DELIVERYTOOMNEON} and ${AIP_STORAGE}."
echo " -n Local mode: formula to be used when making local or test packages. Does not make any deliveries."
echo " -a Audio mode: formula for ingesting audio, similar to preservation mode. Creates access copies, but does not make any deliveries, and creates the package in the same directory as the input."
echo " -e Edit/terminal mode: user specifies file, media ID, and other options through interactive terminal interface prompts."
echo " -h display this help"
echo
exit
}
user_input="${*}"
OPTIND=1
while getopts ":pienah" OPT ; do
case "${OPT}" in
p) MODE="preservation" ;;
i) MODE="psa" ;;
n) MODE="local" ;;
a) MODE="audio" ;;
e) TERMINAL_MODE="Y" ;;
h) _usage ;;
*) echo "bad option -${OPTARG}" ; _usage ;;
:) echo "Option -${OPTARG} requires an argument" ; _writeerrorlog "ingestfile" "You used an invalid option and the script had to exit" ; exit 1 ;;
esac
done
shift $(( ${OPTIND} - 1 ))
#local functions
_add_mediaid_to_queue(){
[ -n "${MEDIAID}" ] || { _report -wt "Error: mediaid is undefined in add_media_to_queue function" ; _writeerrorlog "_add_mediaid_to_queue" "The media id is undefined in the _add_mediaid_to_queue function, and caused the script to exit." ; exit 1 ;};
[ -n "${QUEUEFILE}" ] || { _report -wt "Error: queuefile is undefined in add_media_to_queue function" ; _writeerrorlog "_add_mediaid_to_queue" "The queuefile is undefined in the _add_mediaid_to_queue function, and caused the script to exit." ; exit 1 ;};
echo "${MEDIAID}" >> "${QUEUEFILE}"
}
_remove_mediaid_from_queue(){
[ -n "${MEDIAID}" ] || { _report -wt "Error: mediaid is undefined in remove_media_from_queue function" ; _writeerrorlog "_remove_mediaid_from_queue" "The media id is undefined in the _remove_mediaid_from_queue function, and caused the script to exit." ; exit 1 ;};
[ -f "${QUEUEFILE}" ] || { _report -wt "Error: queuefile is undefined in remove_media_from_queue function" ; _writeerrorlog "_remove_mediaid_from_queue" "The queuefile is undefined in the _remove_mediaid_from_queue function, and caused the script to exit." ; exit 1 ;};
grep -v "^${MEDIAID}$" "${QUEUEFILE}" | grep "^[A-Z0-9_-]\+$" > "${QUEUEFILE}_tmp"
rm "${QUEUEFILE}"
mv "${QUEUEFILE}_tmp" "${QUEUEFILE}"
}
_ask_digitization_logs(){
_report -qn "Drag in any logs from digitization: "
read -e -a FILES
[[ "$FILES[0]" = "q" ]] && exit 0
[[ ! -z "${FILES}" ]] && _writeingestlog "digitization_logs: ${FILES}\n"
}
# spreadsheet fields are currently CUNY-specific
_parse_spreadsheet(){
DIGITIZATIONLOG=$(_maketemp)
paste -d"*" <(ssconvert -T Gnumeric_html:xhtml_range "${FILES}" fd://1 | xmlstarlet fo | xmlstarlet select --no-doc-namespace -t -m "_:html/_:body/_:table[1]/_:tr[1]/_:td" -v "." -n) <(ssconvert -T Gnumeric_html:xhtml_range "${FILES}" fd://1 | xmlstarlet fo | xmlstarlet select --no-doc-namespace -t -m "_:html/_:body/_:table[1]/_:tr[_:td[1]='${MEDIAID}']/_:td" -v "." -n) | sed "s/*/\: /g" | tee "${DIGITIZATIONLOG}"
cat "${DIGITIZATIONLOG}" >> "${INGESTLOG}"
OBJECTSOUNDFIELD=$(_readingestlog "object soundfield")
DECKHEADSETTING=$(_readingestlog "deck head setting")
SAMPLINGRATE=$(_readingestlog "adda converter sr setting")
if [[ "${OBJECTSOUNDFIELD}" == "Mono" ]] && [[ "${DECKHEADSETTING}" == "Two-track head" ]] ; then
AUDIODECISION="Only use left of the first audio track [for 21st Century]"
elif [[ "${OBJECTSOUNDFIELD}" == "Stereo" ]] ; then
AUDIODECISION="Default audio mapping [first audio track used for stereo output]"
fi
if [[ "${SAMPLINGRATE}" == "96k" ]]; then
SAMPLINGRATE=96000
elif [[ "${SAMPLINGRATE}" == "48k" ]]; then
SAMPLINGRATE=48000
fi
}
_get_xmp_info(){
XMP_SIZE=$(mediaconch -mt "${INPUT}" | xmlstarlet sel -N "mt=https://mediaarea.net/mediatrace" -t -m "mt:MediaTrace/mt:media/mt:block[@name='Wave']/mt:block[@name='_PMX']" -v "mt:block[@name='Header']/mt:data[@name='Size']" -n)
XMP_OFFSET=$(mediaconch -mt "${INPUT}" | xmlstarlet sel -N "mt=https://mediaarea.net/mediatrace" -t -m "mt:MediaTrace/mt:media/mt:block[@name='Wave']/mt:block[@name='_PMX']" -v "mt:data/@offset" -n)
XMP_OFFSET=$(echo "${XMP_OFFSET} + 1" | bc)
XMP_DATA=$(tail -c "+${XMP_OFFSET}" "${INPUT}" | head -c "${XMP_SIZE}" | xmlstarlet fo)
GET_INFO=$(echo "${XMP_DATA}" | xmlstarlet sel -N rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" -N xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/" -t -m "//rdf:li[@rdf:parseType='Resource'][xmpDM:trackName='CuePoint Markers']" -o "inSample:" -v "xmpDM:markers/rdf:Seq/rdf:li[@rdf:parseType='Resource']/xmpDM:startTime" -n -o "durationSample:" -v "xmpDM:markers/rdf:Seq/rdf:li[@rdf:parseType='Resource']/xmpDM:duration" -n)
INSAMPLE=$(echo "${XMP_DATA}" | xmlstarlet sel -N rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" -N xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/" -t -m "//rdf:li[@rdf:parseType='Resource'][xmpDM:trackName='CuePoint Markers']" -v "xmpDM:markers/rdf:Seq/rdf:li[@rdf:parseType='Resource']/xmpDM:startTime" -n)
DURATIONSAMPLE=$(echo "${XMP_DATA}" | xmlstarlet sel -N rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" -N xmpDM="http://ns.adobe.com/xmp/1.0/DynamicMedia/" -t -m "//rdf:li[@rdf:parseType='Resource'][xmpDM:trackName='CuePoint Markers']" -v "xmpDM:markers/rdf:Seq/rdf:li[@rdf:parseType='Resource']/xmpDM:duration" -n)
echo "${GET_INFO}"
INTIME=$(echo "scale=4; ${INSAMPLE}/${SAMPLINGRATE}" | bc | awk '{printf "%f", $0}')
DURATION=$(echo "scale=4; ${DURATIONSAMPLE}/${SAMPLINGRATE}" | bc | awk '{printf "%f", $0}')
OUTTIME=$(echo "scale=4; ${INTIME}+${DURATION}" | bc | awk '{printf "%f", $0}')
echo "The intime in samples is $INTIME, the outtime in seconds is $OUTTIME, and the duration in seconds is $DURATION."
}
_audioreport(){
ffmpeg -nostdin -i "${INPUT}" -vn -filter_complex "silencedetect,astats,loudnorm=print_format=json,agate=attack=0.01:release=0.01:ratio=9000,aphasemeter=r=0.2:video=0,ametadata=mode=print:key=lavfi.aphasemeter.phase:value=-0.18:function=less" -f null - 2>&1 | tr "\r" "\n" > /tmp/loud
MEASURED_I=$(cat /tmp/loud | grep "input_i" | awk -F\" '{print $4}')
MEASURED_LRA=$(cat /tmp/loud | grep "input_lra" | awk -F\" '{print $4}')
MEASURED_TP=$(cat /tmp/loud | grep "input_tp" | awk -F\" '{print $4}')
MEASURED_THRESH=$(cat /tmp/loud | grep "input_thresh" | awk -F\" '{print $4}')
TARGET_OFFSET=$(cat /tmp/loud | grep "target_offset" | awk -F\" '{print $4}')
BWFMETAEDIT=$(bwfmetaedit "${INPUT}" 2>&1 | awk '{printf "%s+",$0} END {print ""}')
FLATFACTOR=$(cat /tmp/loud | grep "Flat factor: " | tail -n +3 | head -n 1 | cut -d ":" -f 2 | sed 's/ //g')
echo " MEASURED_I = ${MEASURED_I}"
echo " MEASURED_LRA = ${MEASURED_LRA}"
echo " MEASURED_TP = ${MEASURED_TP}"
echo " MEASURED_THRESH = ${MEASURED_THRESH}"
echo " TARGET_OFFSET = ${TARGET_OFFSET}"
echo " BWFMETAEDIT = ${BWFMETAEDIT}"
if [[ "${FLATFACTOR}" != 0.000000 ]] ; then
_report -wt "WARNING - There are ${FLATFACTOR} flat sections of waveform that may indicate clipped audio."
_report -qn "Enter q to quit, any other key to continue: "
read A4
[ "${A4}" == "q" ] && exit 0
_writeingestlog "Flat sections of audio waveform" "${FLATFACTOR}"
fi
}
_blackframetest(){
_black_at_ends "${INPUT}"
if [ "${HEAD_BLACK}" -gt "30" ] ; then
_report -wt "WARNING - There are at least ${HEAD_BLACK} frames of black at the beginning of ${INPUT}"
_report -qn "Enter q to quit, any other key to continue: "
read A1
[ "${A1}" == "q" ] && exit 0
_ask_intime
fi
if [ "${TAIL_BLACK}" -gt "30" ] ; then
_report -wt "WARNING - There are at least ${TAIL_BLACK} frames of black at the end of ${INPUT}"
_report -qn "Enter q to quit, any other key to continue: "
read A2
[ "${A2}" == "q" ] && exit 0
_ask_outtime
fi
}
_phasechecktest(){
_report -dt "Checking audio phase for $(basename "${INPUT}")"
_get_phase_warning "${INPUT}"
if [ "${PHASE_ERROR}" -gt "0" ] ; then
_report -w "WARNING - There are ${PHASE_ERROR} sections of out-of-phase audio"
_report -qn "Enter q to quit, any other key to continue: "
read A3
[ "${A3}" == "q" ] && exit 0
fi
}
_makebroadcastcopies(){
if [ "${SLATE}" == "Yes" ] ; then
"${SCRIPTDIR}/makederiv" -T broadcast -s "${MAKEDERIVOPTS[@]}" "${OUTDIR_INGESTFILE}/${MEDIAID}"
if [ "${DELIVERYTOOMNEON}" == "Y" ] ; then
_report -dt "STATUS Uploading ${OBJECTSDIR}/service/${MEDIAID%.*}_SLATE.mov to the OMNEON."
"${SCRIPTDIR}/uploadomneon" "${OBJECTSDIR}/service/${MEDIAID%.*}_SLATE.mov"
fi
fi
"${SCRIPTDIR}/makederiv" -T broadcast "${MAKEDERIVOPTS[@]}" "${OUTDIR_INGESTFILE}/${MEDIAID}"
if [ "${DELIVERYTOOMNEON}" == "Y" ] ; then
_report -dt "STATUS Uploading ${OBJECTSDIR}/service/${MEDIAID%.*}.mov to the OMNEON."
"${SCRIPTDIR}/uploadomneon" "${OBJECTSDIR}/service/${MEDIAID%.*}.mov"
fi
}
_deliveraccessopts(){
YOUTUBEOPTS=(-Y -d "${YOUTUBEDELIVER}")
FRAMESOPTS=(-d "${YOUTUBEDELIVER}")
PODCASTOPTS=(-d "${PODCASTDELIVER}")
}
_makeaccesscopies(){
_report -dt "STATUS Making access copies."
"${SCRIPTDIR}/makederiv" -T waveform "${OUTDIR_INGESTFILE}/${MEDIAID}"
if [ "${MODE}" != "audio" ] ; then
"${SCRIPTDIR}/makederiv" -T mp3 "${OUTDIR_INGESTFILE}/${MEDIAID}"
"${SCRIPTDIR}/makeframes" "${FRAMESOPTS[@]}" "${OUTDIR_INGESTFILE}/${MEDIAID}"
"${SCRIPTDIR}/makederiv" -T youtube "${MAKEDERIVOPTS[@]}" "${YOUTUBEOPTS[@]}" "${OUTDIR_INGESTFILE}/${MEDIAID}"
if [ $(echo "${MEDIAID}" | grep -E "${REGEX4PODCAST}") ] ; then
_report -dt "${MEDIAID} qualifies for podcast creation."
"${SCRIPTDIR}/makederiv" -T podcast "${MAKEDERIVOPTS[@]}" "${PODCASTOPTS[@]}" "${OUTDIR_INGESTFILE}/${MEDIAID}"
else
_report -dt "${MEDIAID} does NOT qualify for podcast creation, skipping."
_writeerrorlog "makederiv" -T podcast "${MEDIAID} did not qualify for podcast creation and was skipped."
fi
else
"${SCRIPTDIR}/makederiv" -T mp3 "${MP3OPTS[@]}" "${OUTDIR_INGESTFILE}/${MEDIAID}"
"${SCRIPTDIR}/makederiv" -T podcast "${MAKEDERIVOPTS[@]}" "${PODCASTOPTS[@]}" -e "$MAKEYOUTUBE_DELIVERY_EMAIL_TO" "${OUTDIR_INGESTFILE}/${MEDIAID}"
"${SCRIPTDIR}/makederiv" -T showwaves "${MAKEDERIVOPTS[@]}" "${OUTDIR_INGESTFILE}/${MEDIAID}"
"${SCRIPTDIR}/makederiv" -T audiographs "${OUTDIR_INGESTFILE}/${MEDIAID}"
fi
}
_makemetadatapackage(){
"${SCRIPTDIR}/makemetadata" "${OUTDIR_INGESTFILE}/${MEDIAID}"
"${SCRIPTDIR}/checksumpackage" "${OUTDIR_INGESTFILE}/${MEDIAID}"
if [[ "${MODE}" != "audio" ]] ; then
"${SCRIPTDIR}/makefingerprint" "${OUTDIR_INGESTFILE}/${MEDIAID}"
fi
}
_delivertoaipstorage(){
if [ "${AIP_STORAGE}" != "${OUTDIR_INGESTFILE}" ] ; then
"${SCRIPTDIR}/migratefiles" -r -o "${AIP_STORAGE}" "${OUTDIR_INGESTFILE}/${MEDIAID}"
RSYNC_ERR="${?}"
[ $(du -s "${OUTDIR_INGESTFILE}/${MEDIAID}" | awk '{print $1}') = "0" ] && rm -r "${OUTDIR_INGESTFILE}/${MEDIAID}"
_report -dt "STATUS Done. Final package has been delivered to ${AIP_STORAGE}/${MEDIAID}"
else echo "As Target directory is same as Input directory, files were not migrated."
fi
}
_delivertoia(){
if [ $(echo "${MEDIAID}" | grep -E "${REGEX4IA}") ] ; then
if [ $(which uploadia) ] ; then
_report -dt "Attempting to run uploadia and upload to Internet Archive"
uploadia "${OUTDIR_INGESTFILE}/${MEDIAID}/objects/access/youtube_up/${MEDIAID}.mp4"
fi
fi
}
_writecapturelog(){
echo -e "${LOG}" >> "${INGESTLOG}"
_writeingestlog "media ID" "${MEDIAID}"
_writeingestlog "media ID slate" "${MEDIAID4SLATE}"
_writeingestlog "operator" "${OP}"
_writeingestlog "input" "${INPUT}"
_writeingestlog "processing_directory" "${OUTDIR_INGESTFILE}"
_writeingestlog "audiodecision" "${AUDIODECISION}"
_writeingestlog "cropdecision" "${CROPDECISION}"
_writeingestlog "cleanupdecision" "${CLEANUPDECISION}"
_writeingestlog "formula" "${FORMULA}"
_writeingestlog "ingest_process_dir" "${OUTDIR_INGESTFILE}"
_writeingestlog "ingest_process_dir_freespace" "$(df -h "${OUTDIR_INGESTFILE}" | tail -n1 | awk '{print $4}')"
_writeingestlog "computer_name" "$(uname -n)"
_writeingestlog "user_name" "$(whoami)"
_writeingestlog "operating_system_version" "$(uname -v)"
_writeingestlog "datetime_start" "$(_get_iso8601)"
_writeingestlog "Series Title" "${SERIESTITLE}"
_writeingestlog "Episode Title" "${EPISODETITLE}"
_writeingestlog "made this" "ingestfile"
_writeingestlog "Interlacement test" "${INTERLACETEST}"
if [ -n "$(cat "${PHASEREPORT}" | xargs)" ] ; then
_writeingestlog "Out_of_phase_audio_ranges" "$(cat "${PHASEREPORT}" | xargs)"
else
_writeingestlog "Out_of_phase_audio_ranges" "None"
fi
if [ "${INTIME}" ] ; then
_writeingestlog "intime" "${INTIME}"
fi
if [ "${OUTTIME}" ] ; then
_writeingestlog "outtime" "${OUTTIME}"
fi
if [ "${MODE}" == "preservation" ] ; then
_writeingestlog "package type" "Preservation-Video"
else
_writeingestlog "package type" "Production"
fi
}
_cleanup_ingest(){
_log -a "Process canceled"
_remove_mediaid_from_queue
[ -d "${OUTDIR_INGESTFILE}/${MEDIAID}" ] && mv "${OUTDIR_INGESTFILE}/${MEDIAID}" "${OUTDIR_INGESTFILE}/${MEDIAID}_canceled_ingest_$(_get_iso8601_c)"
exit 1
}
_cleanup_sourcefile(){
if [ -n "${RSYNC_ERR}" ] && [ "${RSYNC_ERR}" -gt "0" ] ; then
echo "${RSYNC_ERR}"
_report -wt "Cancelling requested deletion of source file, not looking safe."
else
_report -dt "Removing the source file from ${INPUT} as requested."
_run rm -f "${INPUT}"
fi
}
_run_storage_checks(){
# for existing output
if [ -d "${OUTDIR_INGESTFILE}/${MEDIAID}" ] ; then
_report -wt "It looks like ${MEDIAID} was already ingested. If you want to overwrite the existing one, please delete ${OUTDIR_INGESTFILE}/${MEDIAID} first and then try again."
exit 1
fi
if [ -d "${AIP_STORAGE}/${MEDIAID}" ] ; then
_report -wt "It looks like ${MEDIAID} was already ingested. If you want to overwrite the existing one, please delete ${AIP_STORAGE}/${MEDIAID} first and then try again."
exit 1
fi
}
_run_input_file_checks(){
# check if file is being modified
INPUT_DATE=$(getfileinfo "${INPUT}" | grep modified | cut -d' ' -f2-)
CURRENT_DATE=$(date -j "+%m/%d/%Y %H:%M:%S")
if [ "${INPUT_DATE}" = "${CURRENT_DATE}" ] ; then
_report -w "WARNING: Input is currently being modified. Exiting."
exit 1
fi
# here is where we would insert an option for searching for directory.
# if file is a video
if [[ "${MODE}" != "audio" ]] ; then
if [ ! $(_is_video "${INPUT}") ] ; then
_report -qnt "WARNING: ${INPUT} is not recognized as a video file. Please press q to quit, any other key to continue (if you know what you're doing):"
read NOTVIDRESPONSE
[ "${NOTVIDRESPONSE}" == "q" ] && exit 0
fi
fi
}
_setup_package(){
# set up package directories
OBJECTSDIR="${OUTDIR_INGESTFILE}/${MEDIAID}/objects"
_run_critical _mkdir2 "${OBJECTSDIR}"
LOGDIR="${OUTDIR_INGESTFILE}/${MEDIAID}/metadata/logs"
_run _mkdir2 "${LOGDIR}"
INGESTLOG="${LOGDIR}/capture.log"
}
trap _cleanup SIGHUP SIGINT SIGTERM
trap _cleanup_ingest SIGHUP SIGINT SIGTERM
# check environment
if [ ! -d "$(pwd)" ] ; then
_report -w "You're in a directory that doesn't actually exist. The script exited and you need to cd into a different directory. ¯\_(ツ)_/¯ "
exit 1
fi
[ -z "${OUTDIR_INGESTFILE}" ] && { echo "The processing directory must be set. Use [ -p /path/to/processing/directory ] or run mmconfig to set OUTDIR_INGESTFILE." ; exit 1 ;};
[ -z "${AIP_STORAGE}" ] && { echo "The AIP Storage directory must be set. Use [ -a /path/to/AIP/storage/directory ] or run mmconfig to set AIP_STORAGE." ; exit 1 ;};
[ -z "${PODCASTDELIVER}" ] && { echo "A directory for podcast delivery must be set. Use [ -w /path/to/deliver/podcastfiles] or run mmconfig to set PODCASTDELIVER." ; exit 1 ;};
[ -z "${YOUTUBEDELIVER}" ] && { echo "A directory for youtube delivery must be set. Use [ -y /path/to/deliver/youtubefiles] or run mmconfig to set YOUTUBEDELIVER." ; exit 1 ;};
# pashua interface settings
CONF="
# Set transparency: 0 is transparent, 1 is opaque
*.transparency=1.00
# Set window title
*.title = Ingest File
# intro text
intro.x = 20
intro.y = 720
intro.width = 500
intro.type = text
intro.text = Ingest file options. Leave the option blank to be prompted.
# ask operator
OP.x = 20
OP.y = 660
OP.type = textfield
OP.label = Please enter your name:
OP.width = 300
# media ID
MEDIAID.x = 20
MEDIAID.y = 600
MEDIAID.type = textfield
MEDIAID.label = Please enter a unique MEDIA ID (capital letters, numbers, hyphens and underscores only).
MEDIAID.width = 300
# input file
INPUT.x = 20
INPUT.y = 540
INPUT.type = openbrowser
INPUT.label = Select your file:
INPUT.width=400
# audio strategy
AUDIODECISION.x = 20
AUDIODECISION.y = 480
AUDIODECISION.type = combobox
AUDIODECISION.label = Select an audio strategy:
AUDIODECISION.default = Default audio mapping [first audio track used for stereo output]
AUDIODECISION.option =
AUDIODECISION.option = Default audio mapping [first audio track used for stereo output]
AUDIODECISION.option = Only use left of the first audio track [for 21st Century]
AUDIODECISION.option = Only use right of the first audio track
AUDIODECISION.option = Only use the first track
AUDIODECISION.option = Downmix the first two mono tracks
AUDIODECISION.option = Downmix all tracks
AUDIODECISION.width = 400
# cropping strategy
CROPDECISION.x = 20
CROPDECISION.y = 420
CROPDECISION.type = combobox
CROPDECISION.label = Select a cropping strategy:
CROPDECISION.default = Do not crop
CROPDECISION.option =
CROPDECISION.option = Do not crop
CROPDECISION.option = Examine the video and auto-crop out black borders (slower)
CROPDECISION.width = 400
# adding slate
SLATE.x = 20
SLATE.y = 360
SLATE.type = combobox
SLATE.label = Do you want to create a service copy with a slate?
SLATE.default = No
SLATE.option =
SLATE.option = Yes
SLATE.option = No
SLATE.width = 100
# slate information: series title
SERIESTITLE.x = 20
SERIESTITLE.y = 300
SERIESTITLE.type = textfield
SERIESTITLE.label = If adding slate, please enter a series title:
SERIESTITLE.width = 300
# slate information: episode title
EPISODETITLE.x = 20
EPISODETITLE.y = 240
EPISODETITLE.type = textfield
EPISODETITLE.label = If adding slate, please enter an episode title:
EPISODETITLE.width = 300
# formula
FORMULA.x = 20
FORMULA.y = 180
FORMULA.type = combobox
FORMULA.label = Select a formula for unusual cases (optional).
FORMULA.tooltip = To force the input file to be interpreted as top or bottom field first interlacement, select tff or bff. To stretch the input video to 1920x1080 HD frame size, select 'HDS'.
FORMULA.default = none
FORMULA.option =
FORMULA.option = none
FORMULA.option = check interlacement
FORMULA.option = tff
FORMULA.option = bff
FORMULA.option = hds
FORMULA.option = sds
FORMULA.width = 300
# cleanup decision
CLEANUPDECISION.x = 20
CLEANUPDECISION.y = 120
CLEANUPDECISION.type = combobox
CLEANUPDECISION.label = Select a cleanup strategy
CLEANUPDECISION.default = Leave source file where it is
CLEANUPDECISION.option =
CLEANUPDECISION.option = Leave source file where it is
CLEANUPDECISION.option = Remove source file after successful ingest
CLEANUPDECISION.width = 300
# priority
PRIORITY.x = 20
PRIORITY.y = 60
PRIORITY.type = combobox
PRIORITY.label = Would you like to put it in the queue or start now?
PRIORITY.default = put in queue
PRIORITY.option =
PRIORITY.option = put in queue
PRIORITY.option = start now
PRIORITY.width = 300
# start time
INTIME.x = 340
INTIME.y = 120
INTIME.type = textfield
INTIME.label = Enter a start time (HH:MM:SS.mmm)
INTIME.width = 100
# end time
OUTTIME.x = 340
OUTTIME.y = 60
OUTTIME.type = textfield
OUTTIME.label = Enter a end time (HH:MM:SS.mmm)
OUTTIME.width = 100
# Add a cancel button with default label
cb.type=cancelbutton
";
# run gui
if [ "${TERMINAL_MODE}" != "Y" ] ; then
PASHUA_CONFIGFILE=`/usr/bin/mktemp /tmp/pashua_XXXXXXXXX`
echo "${CONF}" > "${PASHUA_CONFIGFILE}"
_pashua_run
rm "${PASHUA_CONFIGFILE}"
echo " OPERATOR = ${OP}"
echo " INPUT = ${INPUT}"
echo " MEDIAID = ${MEDIAID}"
echo " AUDIODECISION = ${AUDIODECISION}"
echo " CROPDECISION = ${CROPDECISION}"
echo " SLATE = ${SLATE}"
echo " SERIESTITLE = ${SERIESTITLE}"
echo " EPISODETITLE = ${EPISODETITLE}"
echo " FORMULA = ${FORMULA}"
echo " CLEANUPDECISION = ${CLEANUPDECISION}"
echo " PRIORITY = ${PRIORITY}"
echo ""
fi
if [[ "${cb}" -eq 1 ]] ; then
exit 1
fi
if [ ! -z $(echo "${MEDIAID}" | grep -v "^[A-Z0-9_-]*$") ] ; then
echo "Error: The MEDIA ID must only contain capital letters, numbers, hyphens and underscores."
echo "Please enter a valid MEDIA ID:"
MEDIAID=""
_ask_mediaid
fi
# interview the operator
_ask_operator
_ask_mediaid
_run_storage_checks
_ask_input
_run_input_file_checks
if [[ "${MODE}" == "preservation" ]] ; then
OUTDIR_INGESTFILE=$(dirname "${INPUT}")
_report -dt "I'm going to place the AIP in the same directory as the original input file."
fi
_setup_package
if [[ "${MODE}" == "audio" ]] ; then
_report -q "Is the file the result of digitization? Enter 1 for Yes or 2 for No."
select DIGITIZATION in "Yes" "No"
do
break
done
if [[ "${DIGITIZATION}" == "Yes" ]] ; then
_ask_digitization_logs
_ask_photos "${MEDIAID}"
if [[ -f ${FILES} ]] ; then
_parse_spreadsheet
_get_xmp_info
fi
fi
fi
if [[ -z "${AUDIODECISION}" ]] ; then
_report -q "Select an audio strategy?"
PS3="Selection: "
select AUDIODECISION in "Default audio mapping [first audio track used for stereo output]" "Only use left of the first audio track [for 21st Century]" "Only use right of the first audio track" "Only use the first track" "Downmix the first two mono tracks" "Downmix all tracks"
do
break
done
fi
if [[ -z "${CROPDECISION}" ]] && [[ "${MODE}" != "audio" ]] ; then
_report -q "Select a cropping strategy?"
PS3="Selection: "
select CROPDECISION in "Do not crop." "Examine the video and auto-crop out black borders (slower)"
do
break
done
fi
if [[ -z "${FORMULA}" ]] && [[ "${MODE}" != "audio" ]] ; then
_report -q "Select an optional formula for unusual cases?"
_report -d "(In most cases, select 'none'. To force the input file to be interpreted as top or bottom field first interlacement, select tff or bff. To stretch the input video to 1920x1080 HD frame size, select 'hds'. To squish into Standard Definition, select 'sds'.)"
PS3="Selection: "
select FORMULA in "none" "check interlacement" "tff" "bff" "hds" "sds"
do
break
done
fi
if [[ -z "${CLEANUPDECISION}" ]] ; then
_report -q "Select a cleanup strategy?"
select CLEANUPDECISION in "Leave source file where it is." "Remove source file after successful ingest"
do
break
done
fi
if [[ -z "${PRIORITY}" ]] ; then
_report -q "Select a multitasking strategy?"
select PRIORITY in "put in queue" "start now"
do
break
done
fi
if [[ -z "${SLATE}" ]] && [[ "${MODE}" != "audio" ]] ; then
_report -q "Do you want to create a service copy with a slate?"
select SLATE in "Yes" "No"
do
break
done
fi
if [[ "${SLATE}" == "Yes" ]] ; then
if [[ -z "${SERIESTITLE}" ]] ; then
cowsay -t "Series Title?"
echo -n ":: "
read SERIESTITLE
fi
if [[ -z "${EPISODETITLE}" ]] ; then
cowsay -s "Episode Title?"
echo -n ":: "
read EPISODETITLE
fi
MEDIAID4SLATE="${MEDIAID}"
fi
# MICROSERVICES BEFORE PROCESSING
if [[ "${MODE}" == "preservation" ]] ; then
_ask_digitization_logs
if [[ "${INPUT#*.}" = "mkv" ]] ; then
"${SCRIPTDIR}/makemkvchapters" "${INPUT}"
else
_ask_intime
_ask_outtime
fi
_get_frame_count "${INPUT}"
if [[ "${FORMULA}" == "check interlacement" ]] ; then
_get_interlacement_full "${INPUT}"
fi
elif [[ "${MODE}" == "audio" ]] ; then
_audioreport
else
# presumes default, psa, or local mode
_blackframetest
_phasechecktest
_get_frame_count "${INPUT}"
if [[ "${FORMULA}" == "check interlacement" ]] ; then
_get_interlacement_full "${INPUT}"
fi
fi
# queue handling
if [ "${PRIORITY}" = "put in queue" ] ; then
_add_mediaid_to_queue
NEXT=$(head -n 1 "${QUEUEFILE}")
while [ "${MEDIAID}" != "${NEXT}" ] ; do
NEWNEXT=$(head -n 1 "${QUEUEFILE}")
echo -n "This process is waiting behind these identifiers: "
cat "${QUEUEFILE}" | tr '\n' ' '
echo
while [ "${NEXT}" = "${NEWNEXT}" ] ; do
sleep 10
NEWNEXT=$(head -n 1 "${QUEUEFILE}")
done
NEXT="${NEWNEXT}"
done
fi
_log -b
_writecapturelog
# rsync
# make sure the input is still there
if [ ! -f "${INPUT}" ] ; then
_report -wt "The input file is no longer available! Where did $(basename "${INPUT}") go? Please redo."
_writeerrorlog "ingestfile" "The input file, $(basename "${INPUT}"), was no longer available, so ingest file could not continue."
# clean up queue
[ "${PRIORITY}" == "put in queue" ] && _cleanup_ingest
exit 1
fi
# either rsync or mv the input into the package
FROM=$(_get_filesystem "${INPUT}")
TO=$(_get_filesystem "${OBJECTSDIR}/")
if [ "${FROM}" == "${TO}" -a "${CLEANUPDECISION}" == "Remove source file after successful ingest" ] ; then
_report -dt "Because ${INPUT} and ${OBJECTSDIR} are on the same filesystem and preservation mode is enabled we will mv rather than rsync."
_run_critical mv -v -n "${INPUT}" "${OBJECTSDIR}/"
if [ ! "${#FILES[@]}" = 0 ] ; then
_run_critical mv -v -n "${FILES[@]}" "${LOGDIR}/"
fi
else
_report -dt "STATUS Copying the original file to library storage at ${OBJECTSDIR}."
LOGFILE="${LOGDIR}/rsync_$(_get_iso8601_c)_$(basename ${0})_${VERSION}.txt"
"${SCRIPTDIR}/migratefiles" -l "${LOGFILE}" -o "${OBJECTSDIR}" "${INPUT}"
if [ ! "${#FILES[@]}" = 0 ] ; then
_run_critical rsync -rt --progress --log-file="${LOGDIR}/rsync_$(_get_iso8601_c)_$(basename $0)_${VERSION}.txt" "${FILES[@]}" "${LOGDIR}/"
fi
fi
# set makederivopts
unset MAKEDERIVOPTS
if [[ "${CROPDECISION}" == "Examine the video and auto-crop out black borders (slower)" ]] ; then
MAKEDERIVOPTS+=(-c)
fi
if [[ ! -z "${FORMULA}" ]] ; then
MAKEDERIVOPTS+=(-F "${FORMULA}")
fi
# SELECT MICROSERVICES PER MODE
if [[ "${MODE}" == "preservation" ]] ; then
_makebroadcastcopies
_makeaccesscopies
_makemetadatapackage
_writeingestlog "datetime_end" "$(_get_iso8601)"
elif [[ "${MODE}" == "psa" ]] ; then
DELIVERYTOOMNEON="Y"
_makebroadcastcopies
_makeaccesscopies
_makemetadatapackage
_writeingestlog "datetime_end" "$(_get_iso8601)"
_delivertoaipstorage
elif [[ "${MODE}" == "local" ]] ; then
_makebroadcastcopies
_makeaccesscopies
_makemetadatapackage
_writeingestlog "datetime_end" "$(_get_iso8601)"
_delivertoaipstorage
elif [[ "${MODE}" == "audio" ]] ; then
_deliveraccessopts
_makeaccesscopies
_makemetadatapackage
_writeingestlog "datetime_end" "$(_get_iso8601)"
_delivertoaipstorage
else
# presuming 'default' mode
DELIVERYTOOMNEON="Y"
_makebroadcastcopies
_deliveraccessopts
_makeaccesscopies
_delivertoia
_makemetadatapackage
_writeingestlog "datetime_end" "$(_get_iso8601)"
_delivertoaipstorage
if [[ "${CLEANUPDECISION}" = "Remove source file after successful ingest" ]] ; then
_cleanup_sourcefile
fi
fi
# clean up queue
[ "${PRIORITY}" == "put in queue" ] && _remove_mediaid_from_queue
_report_to_db