forked from NMAAHC/nmaahcmm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
mkvnote
executable file
·319 lines (266 loc) · 11.7 KB
/
mkvnote
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
#!/bin/bash
# The shebang above specifies that this script should be run with bash.
# Declaration of arrays containing tag names for two different sets of metadata standards: JPC and NMAAHC.
# These tags are predefined fields that will be used to store specific pieces of information about the video files.
MKV_TAG_SET_JPC=(
"COLLECTION"
"TITLE"
"CATALOG_NUMBER"
"DESCRIPTION"
"DATE_DIGITIZED"
"ENCODING_SETTINGS"
"ENCODED_BY"
"ORIGINAL_MEDIA_TYPE"
"DATE_TAGGED"
"TERMS_OF_USE"
"_TECHNICAL_NOTES"
"_ORIGINAL_FPS"
)
MKV_TAG_SET_NMAAHC=(
"COLLECTION"
"TITLE"
"CATALOG_NUMBER"
"DESCRIPTION"
"DATE_DIGITIZED"
"ENCODING_SETTINGS"
"ENCODED_BY"
"ORIGINAL_MEDIA_TYPE"
"DATE_TAGGED"
"TERMS_OF_USE"
"_TECHNICAL_NOTES"
"_ORIGINAL_FPS"
"_TAGTAG" # Unique to the NMAAHC set, suggesting an additional, possibly custom, tag.
)
# Color variables for formatting output text. Utilizes `tput` for setting text styles and colors.
# These variables enhance readability and user interface experience.
BOLD=$(tput bold) # Sets bold style for text.
RESET=$(tput sgr0) # Resets text style to default.
GB=$(tput setaf 38) # Sets color of text to greenish-blue.
ERROR=$(tput setaf 1) # Sets color of text to red.
# Function _usage prints the script's usage instructions to the console.
# It's invoked when the script is run without arguments or if the user needs help.
_usage(){
cat <<EOF
$(basename "${0}")
This application will embed key:value pairs ("tags") into a Matroska file in accordance with NMAAHC guidelines.
Usage: $(basename "${0}") [-p|--profile <profile>] /path/to/file
Some key:value pairs have controlled vocabulary.
Tags:
${BOLD}${GB}_IDENTIFIER${RESET}
Free text.
Enter in NMAAHC Object ID#.
ex. 2012.79.1.16.1a
${BOLD}${GB}_ALTERNATE_IDENTIFIER${RESET}
Free text.
Enter in NMAAHC TR#.
ex. TR2011-71.173
${BOLD}${GB}TITLE${RESET}
Free text.
Please provide a title for this file.
ex. Black Journal: Alice Coltrane
${BOLD}${GB}DESCRIPTION${RESET}
Free text.
Please provide a brief description of the content in this file.
ex. A segment from the public television series Black Journal focusing the life and music of Alice Coltrane
and her children in the wake of the death of her husband, famed jazz musician John Coltrane.
This film was shot sometime during 1970; three years after the death of John Coltrane.
She discusses her musical career and how she balances that with being a mother and paying tribute to her late husband,
but also not want
${BOLD}${GB}DATE_DIGITIZED${RESET}
${BOLD}${GB}ORIGINAL_MEDIA_FORMAT${RESET}
Controlled vocab.
Please choose the original format this file was derived from.
controlled vocab list:
1 inch videotape
2 inch videotape
½ inch videotape
U-matic
Betacam
Betamax
Digital Betacam
VHS
MiniDV
D2
DVD
Hi-8
8mm film
Super 8mm film
16mm film
Super 16mm film
35mm film
${BOLD}${GB}_ORIGINAL_PROJECTION_SPEED${RESET}
If the originating format for this file was motion picture film, please provide a projection speed.
ex. 24fps, 18fps, etc.
${BOLD}${GB}_CODING_HISTORY${RESET}
Please provide a coding history for this file.
ex. O=VHS, C=Color, S=Analog, VS= NTSC, F=24, A=4:3, R=640×480,
T=Sony SVO-5800, O=FFV1mkv, C=Color, V=Composite, S=Analog Stereo,
F=24, A=4:3, W=10-bit, R=640×480, M=YUV422p10, T=Blackmagic UltraStudio 4K Mini SN123456, ffmpeg vrecord, in-house,
O=FFV1mkv, W=10-bit, R640x480, MYUV422p10 N=Emily Nabasny
${BOLD}${GB}_TECHNICAL_TRANSFER_NOTES${RESET}
${BOLD}${GB}_CAMERERA_MAKE_MODEL${RESET}
Controlled vocab.
For files created from digital camera cards.
controlled vocab list:
Canon C300
Canon C100
${BOLD}${GB}_CAMERA_CARD_SCRIPT${RESET}
Please enter the script used to repackage the original camera card into an NMAAHC AIP
${BOLD}${GB}_FILE_CREATOR${RESET}
ex. Smithsonian NMAAHC
Tags beginning with an underscore are not part of the "official" set of Matroska tags.
See the nmaachmm README for more information on package definitions.
EOF
exit
}
# Variable initialization for selected profile and tag set.
SELECTED_PROFILE=""
SELECTED_TAG_SET=()
# command-line options to set media id and original variables
OPTIND=1
while getopts ":hp:" opt ; do
case "${opt}" in
p) SELECTED_PROFILE="${OPTARG}" ;;
h) _usage ;;
:) echo "Option -${OPTARG} requires an argument" ; _usage ;;
*) echo "bad option -${OPTARG}" ; _usage ;;
esac
done
shift "$((OPTIND-1))"
# Checks if the script was run without any arguments.
# If no arguments are provided, the _usage function is called to display usage information and the script exits.
if [[ "${#}" -eq 0 ]]; then
_usage
fi
# Assigning the MKV file path as the first argument after getopts are processed.
MKV_FILE="${1}"
# Parsing command line options to set the profile and corresponding tag set.
if [[ "${SELECTED_PROFILE}" == "jpc" ]] ; then
SELECTED_TAG_SET=("${MKV_TAG_SET_JPC[@]}")
elif [[ "${SELECTED_PROFILE}" == "nmaahc" ]] ; then
SELECTED_TAG_SET=("${MKV_TAG_SET_NMAAHC[@]}")
else
unset SELECTED_PROFILE # clear the invalid profiles since it's not one of the ones listed in the if/elif conditions above
echo -e "${BOLD}${ERROR}\nNote: Invalid profile or no profile specified with -p. You will be prompted to select a profile.${RESET}"
fi
# Function _maketemp creates a temporary file and checks for success.
# It's used for creating temporary files for storing intermediate data.
_maketemp(){
mktemp -q -t "$(basename "${0}")"
if [ "${?}" -ne 0 ]; then
echo "${0}: ${ERROR}Can't create temp file, exiting...${RESET}"
exit 1
fi
}
# Display available tag options and prompt for selection if no profile was selected
if [ -z "${SELECTED_PROFILE}" ]; then
echo -e "${GB}\nAvailable tag profiles and their respective tags:${RESET}"
echo -e "${BOLD}\n1) JPC profile tags:${RESET}"
for TAG in "${MKV_TAG_SET_JPC[@]}"; do
echo -e " - $TAG"
done
echo -e "${BOLD}\n2) NMAAHC profile tags:${RESET}"
for TAG in "${MKV_TAG_SET_NMAAHC[@]}"; do
echo -e " - $TAG"
done
while true; do
echo -e "${GB}${BOLD}\nYou must select a tag profile."
echo -e "Press 1 for JPC, 2 for NMAAHC, or 0 to exit.\n"
read -p "Enter your choice: ${RESET}" choice
case "$choice" in
1)
SELECTED_TAG_SET=("${MKV_TAG_SET_JPC[@]}")
SELECTED_PROFILE="jpc"
break # Exit the loop after selection
;;
2)
SELECTED_TAG_SET=("${MKV_TAG_SET_NMAAHC[@]}")
SELECTED_PROFILE="nmaahc"
break # Exit the loop after selection
;;
0)
echo -e "${ERROR}\nExiting...${RESET}"
exit 0
;;
*)
echo "Invalid choice. Please try again."
;;
esac
done
fi
# After ensuring a profile is selected, the script proceeds to handle the .mkv file provided by the user.
# A placeholder for a function call to check if the provided file is indeed an MKV file. This is an important validation step to ensure the script operates on valid input.
#todo _check_if_mkv "${MKV_FILE}"
MKV_FILE_NAME="$(basename "${MKV_FILE}")" # Extracts the file name from the MKV file path.
# Creates a temporary text file to hold the tags and a temporary XML file for drafting the MKV metadata. The tag template will be used for user input, while the XML draft will be used for embedding metadata into the MKV file.
EXISTING_TAGS="$(_maketemp).txt"
XML_DRAFT="$(_maketemp).xml"
mkvextract tags "${MKV_FILE}" | xmlstarlet sel -t -m "/Tags/Tag[Targets='' or not(Targets) or (Targets/TargetTypeValue='50' and not(Targets/TrackUID))]/Simple" -v "Name" -o "=" -v "String" -n >> "${EXISTING_TAGS}"
IS_FIRST="Y"
while IFS="=" read -r EXISTING_KEY EXISTING_VALUE ; do
if [[ ! ${DIALOG_LIST[*]} =~ "\"${EXISTING_KEY}\"" ]] ; then
if [[ ! "${IS_FIRST}" = "Y" ]] ; then
DIALOG_LIST+=(",
")
fi
IS_FIRST="N"
DIALOG_LIST+=("{\"title\" : \"${EXISTING_KEY}\", \"value\" : \"${EXISTING_VALUE}\", \"prompt\" : \"Existing tag\"}")
fi
done < "${EXISTING_TAGS}"
for PROFILE_TAG in "${SELECTED_TAG_SET[@]}" ; do
if [[ "$(grep -c "^${PROFILE_TAG}=" "${EXISTING_TAGS}")" = "0" && ! ${DIALOG_LIST[*]} =~ "\"${PROFILE_TAG}\"" ]] ; then
if [[ ! "${IS_FIRST}" = "Y" ]] ; then
DIALOG_LIST+=(",
")
fi
IS_FIRST="N"
DIALOG_LIST+=("{\"title\" : \"${PROFILE_TAG}\", \"prompt\" : \"A ${SELECTED_PROFILE} profile tag\"}")
fi
done
DIALOG_FORM="$(_maketemp).xml"
cat << EOF > "${DIALOG_FORM}"
{
"title" : "NMAAHC MKV Tagging for ${MKV_FILE_NAME}",
"icon" : "/Applications/Remote Desktop.app",
"ontop" : 1,
"moveable" : 1,
"width" : "75%",
"height" : "75%",
"background" : "color=#800080",
"message" : "These tags semantically are intended to describe the file as a whole and not intended to specifically refer to a particular track or attachment or other sort of piece of the file. Empty tags will be ignored. If you edit exisitng tags here they will be overwritten when saved.",
"infobox" : "### Aditional Info\n\n#### To upload your key:value tag data in .csv \n - choose a .csv file to upload \n - choose a directory where the .mkv you wish to tag are \n - click the 'File Style' button on the bottom left \n - be cool \n#### To tag file via this gui \n - click the 'Tag-On' button on the bottom left \n - follow the instructions",
"textfield" : [
${DIALOG_LIST[@]}
],
"button1text" : "Tag-On!!",
"button2text" : "Cancel"
}
EOF
DIALOG_RESULT="$(dialog --jsonfile "${DIALOG_FORM}")"
if [[ "${DIALOG_RESULT}" == "JSON import failed" ]] ; then
echo "Error loading the form with ${MKV_FILE}"
exit
elif [[ -z "${DIALOG_RESULT}" ]] ; then
echo "cancelled"
exit
else
# Starts the XML draft for MKV metadata embedding with a root Tags element.
echo "<Tags><Tag></Tag></Tags>" > "${XML_DRAFT}"
# Reads the edited tag template line by line, extracting tag names and values entered by the user.
# Only lines that conform to the expected format (tag_name=[tag_value]) are processed.
while read TAG_LINE ; do
# Extracts the tag name by splitting the line at the colon and taking the first part.
TAG_NAME="$(echo "${TAG_LINE}" | cut -d ":" -f1 | sed 's/ $//g')"
# Extracts the tag value by splitting the line at the colon and taking the second part.
TAG_VALUE="$(echo "${TAG_LINE}" | cut -d ":" -f2- | sed 's/^ //g')"
# If the tag value is not empty, the tag is added to the XML draft for embedding.
# The xmlstarlet tool is used to edit the XML structure, ensuring each tag is uniquely added.
if [[ -n "${TAG_VALUE// /}" ]] ; then
xml ed --omit-decl --inplace --subnode "/Tags/Tag[not(Simple/Name='${TAG_NAME}')]" --type elem -n "Simple" --subnode "/Tags/Tag/Simple[not(Name)]" --type elem -n "Name" -v "${TAG_NAME}" --subnode "/Tags/Tag/Simple[not(String)]" --type elem -n "String" -v "${TAG_VALUE}" "${XML_DRAFT}"
fi
done < <(echo "${DIALOG_RESULT}" | grep -v " : $" | sed 's/* : / : /g')
# Uses mkvpropedit to embed the prepared XML metadata into the MKV file, effectively tagging the file.
mkvpropedit --tags "global:${XML_DRAFT}" "${MKV_FILE}"
# A fun message to indicate the completion of the tagging process, potentially using the cowsay program.
cowsay "Cool. Done. Enjoy. Tag-on. ${MKV_FILE}.${RESET}"
fi