From 3a0f224b47a5bdf4304568113829033588e7c0d5 Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Tue, 25 Aug 2026 10:28:48 -0400 Subject: [PATCH 1/8] remove redundant rule --- vrecord | 1 - 1 file changed, 1 deletion(-) diff --git a/vrecord b/vrecord index fa261f70..b70f5953 100755 --- a/vrecord +++ b/vrecord @@ -2808,7 +2808,6 @@ CONTAINER_MATROSKA_TEST=' ' CODEC_GENERAL_TEST=' - YUV CFR YUV From 1976d536c0ea32974873644dc4ceba2fb98e583a Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Tue, 25 Aug 2026 10:30:51 -0400 Subject: [PATCH 2/8] brackets --- vrecord | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vrecord b/vrecord index b70f5953..7b2f603c 100755 --- a/vrecord +++ b/vrecord @@ -3564,7 +3564,7 @@ if [[ "${DEVICE_INPUT_CHOICE}" = 0 ]] ; then fi # policy checks with mediaconch - if "$MEDIACONCH_INSTALLED" ; then + if "${MEDIACONCH_INSTALLED}" ; then _report -d "Checking file conformance against a mediaconch policy..." STATUS=$(mediaconch -fx -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" | xmlstarlet sel -N mc="https://mediaarea.net/mediaconch" -t -v mc:MediaConch/mc:media/mc:policy/@outcome -n) if [[ "${STATUS}" = "pass" ]] ; then From c970b198b61e85e65d6de4d7e2e26ff0fb5731b3 Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Tue, 25 Aug 2026 11:03:37 -0400 Subject: [PATCH 3/8] mediaconch report management updates --- vrecord | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/vrecord b/vrecord index 7b2f603c..fe78056b 100755 --- a/vrecord +++ b/vrecord @@ -3566,21 +3566,27 @@ if [[ "${DEVICE_INPUT_CHOICE}" = 0 ]] ; then # policy checks with mediaconch if "${MEDIACONCH_INSTALLED}" ; then _report -d "Checking file conformance against a mediaconch policy..." - STATUS=$(mediaconch -fx -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" | xmlstarlet sel -N mc="https://mediaarea.net/mediaconch" -t -v mc:MediaConch/mc:media/mc:policy/@outcome -n) + MEDIACONCH_REPORT="${DIR}/${FULL_OUTPUT_ID}_mediaconchreport.xml" + MEDIACONCH_REPORT_TMP="$(_maketemp _mediaconchreport.xml)" + MEDIACONCH_POLICY="${DIR}/${FULL_OUTPUT_ID}_mediaconch_policy.xml" + mediaconch -fx -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" | xmlstarlet fo > "${MEDIACONCH_REPORT_TMP}" + STATUS="$(xmlstarlet sel -N mc="https://mediaarea.net/mediaconch" -t -v mc:MediaConch/mc:media/mc:policy/@outcome -n "${MEDIACONCH_REPORT_TMP}")" if [[ "${STATUS}" = "pass" ]] ; then _report -dt "File passed policy check for the video." _writeingestlog "mediaconch_outcome" "passed" elif [[ "${STATUS}" = "fail" ]] ; then _report -wt "File did not pass vrecord policy check and may not conform to digital preservation standards." - mediaconch -fx -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" | xmlstarlet fo > "${DIR}/${FULL_OUTPUT_ID}_mediaconchreport.xml" - _mv_tmp_file "${MEDIACONCH_POLICY_TMP}" "${DIR}/${FULL_OUTPUT_ID}_mediaconch_policy.xml" - _writeingestlog "mediaconch_outcome" "failed ${DIR}/${FULL_OUTPUT_ID}_mediaconch_policy.xml" - _report -wt "See ${DIR}/${FULL_OUTPUT_ID}_mediaconchreport.xml for a full MediaConch policy report." + _mv_tmp_file "${MEDIACONCH_REPORT_TMP}" "${MEDIACONCH_REPORT}" + _mv_tmp_file "${MEDIACONCH_POLICY_TMP}" "${MEDIACONCH_POLICY}" + _writeingestlog "mediaconch_outcome" "failed ${MEDIACONCH_POLICY}" + _report -wt "See ${MEDIACONCH_REPORT} for a full MediaConch policy report." _report -wt "Or review this attempt to summarize the issue:" - xmlstarlet edit -N "mc=https://mediaarea.net/mediaconch" -d "//*[@outcome='pass']" "${DIR}/${FULL_OUTPUT_ID}_mediaconchreport.xml" + xmlstarlet edit -N "mc=https://mediaarea.net/mediaconch" -d "//*[@outcome='pass']" "${MEDIACONCH_REPORT}" | xmlstarlet fo else - _report -wt "Mediaconch ended in an unexpected way (${STATUS}). Here is its output." - mediaconch -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" + _report -wt "Mediaconch ended in an unexpected way (status: ${STATUS}). Here is its output." + _report -wt "${MEDIACONCH_REPORT}:" + cat "${MEDIACONCH_REPORT}" + _writeingestlog "mediaconch_outcome" "error ${STATUS}" fi fi From 9602ed4ae0ffdca9eb7b81cbf8e939c0eb06a559 Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Tue, 25 Aug 2026 11:08:14 -0400 Subject: [PATCH 4/8] add test for file truncation --- vrecord | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/vrecord b/vrecord index fe78056b..ac0dd1d4 100755 --- a/vrecord +++ b/vrecord @@ -2919,6 +2919,18 @@ _add_mediaconch_rule_set(){ fi } +_check_file_truncation() { + TEST_FILE="${1}" + TEST_LABEL="${2}" + if [[ -f "${TEST_FILE}" ]] ; then + IS_TRUNCATED=$(mediainfo --Output=XML "${TEST_FILE}" | xmlstarlet sel -t -v "//*[local-name()='IsTruncated']" -n 2>/dev/null || echo "") + if [[ "${IS_TRUNCATED}" = "Yes" ]] ; then + cowsay "$(_report -w "WARNING: MediaInfo reports that the ${TEST_LABEL} file (${TEST_FILE}) may be truncated or incomplete.")" + fi + _writeingestlog "${TEST_LABEL}_truncated" "${IS_TRUNCATED}" + fi +} + _add_fadgi_header2vtt(){ VTT_FILE="${1}" VTT_TYPE="${2}" @@ -3590,6 +3602,9 @@ if [[ "${DEVICE_INPUT_CHOICE}" = 0 ]] ; then fi fi + # check file truncation + _check_file_truncation "${VRECORD_OUTPUT}" "preservation" + # embed logs in Matroska files if "$MKVPROPEDIT_INSTALLED" ; then if [[ "${CONTAINER_CHOICE}" = "Matroska" ]] && [[ "${EMBED_LOGS_CHOICE}" = "Yes" ]] ; then From 0497f2f36e366ac0475006ba6068038720e238a4 Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Tue, 25 Aug 2026 11:08:47 -0400 Subject: [PATCH 5/8] add truncation test for access mp4 as well --- vrecord | 3 +++ 1 file changed, 3 insertions(+) diff --git a/vrecord b/vrecord index ac0dd1d4..2f03c9ec 100755 --- a/vrecord +++ b/vrecord @@ -3604,6 +3604,9 @@ if [[ "${DEVICE_INPUT_CHOICE}" = 0 ]] ; then # check file truncation _check_file_truncation "${VRECORD_OUTPUT}" "preservation" + if [[ "${MP4_CHOICE}" = "true" ]] && [[ -f "${MP4NAME}" ]] ; then + _check_file_truncation "${MP4NAME}" "access_mp4" + fi # embed logs in Matroska files if "$MKVPROPEDIT_INSTALLED" ; then From 27ecda61016e2bcbf90b8564189237cc4fe69d29 Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Tue, 25 Aug 2026 11:20:15 -0400 Subject: [PATCH 6/8] reposition a few policies --- vrecord | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/vrecord b/vrecord index 2f03c9ec..67a4d1ab 100755 --- a/vrecord +++ b/vrecord @@ -2003,10 +2003,12 @@ _lookup_choice(){ # audio codec "24-bit PCM") + _add_mediaconch_rule_set "${AUDIO_CODEC_PCM_TEST}" MIDDLEOPTIONS_PRES+=(-c:a pcm_s24le) MIDDLEOPTIONS_PRES+=(-rf64 auto) AUDIO_EXT='wav' ;; "24-bit FLAC") + _add_mediaconch_rule_set "${AUDIO_CODEC_FLAC_TEST}" MIDDLEOPTIONS_PRES+=(-c:a flac) MIDDLEOPTIONS_PRES+=(-sample_fmt s32) MIDDLEOPTIONS_PRES+=(-bits_per_raw_sample:a 24) @@ -3155,11 +3157,6 @@ if [[ ! "${VIDEO_CODEC_CHOICE}" = "h264" ]] ; then _add_mediaconch_rule_set "${CODEC_GENERAL_TEST}" fi _add_mediaconch_rule_set "${AUDIO_CODEC_GENERAL_TEST}" -if [[ "${AUDIO_CODEC_CHOICE}" = "24-bit PCM" ]] ; then - _add_mediaconch_rule_set "${AUDIO_CODEC_PCM_TEST}" -elif [[ "${AUDIO_CODEC_CHOICE}" = "24-bit FLAC" ]] ; then - _add_mediaconch_rule_set "${AUDIO_CODEC_FLAC_TEST}" -fi # CLI passthrough and audiopassthrough modes if [[ "${RUNTYPE}" = "passthrough" ]] ; then From df4de5d55eb46d9f8d87836e13573f8b016b9e5c Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Tue, 25 Aug 2026 11:20:29 -0400 Subject: [PATCH 7/8] fix a description so it applies for all tests --- vrecord | 1 + 1 file changed, 1 insertion(+) diff --git a/vrecord b/vrecord index 67a4d1ab..8566f52f 100755 --- a/vrecord +++ b/vrecord @@ -2904,6 +2904,7 @@ cat < "${MEDIACONCH_POLICY_TMP}" This policy tests FFV1 Matroska and Quicktime files made using vrecord and checks their validity + This policy tests video files made using vrecord and checks their validity against vrecord's specifications MC_START } From 2c11cb6f6c65adec1413bcdabfa677126959f967 Mon Sep 17 00:00:00 2001 From: Dave Rice Date: Tue, 25 Aug 2026 11:32:28 -0400 Subject: [PATCH 8/8] add mediaconch tests for the access mp4 --- vrecord | 101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 98 insertions(+), 3 deletions(-) diff --git a/vrecord b/vrecord index 8566f52f..f95a49bb 100755 --- a/vrecord +++ b/vrecord @@ -2896,6 +2896,52 @@ AUDIO_CODEC_FLAC_TEST=' 24 ' + +CONTAINER_MP4_TEST=' + mp4 + MPEG-4 + Base Media +' + +CODEC_H264_TEST=' + AVC + 4:2:0 + Progressive + CFR +' + +STANDARD_NTSC_ACCESS_DEINTERLACED_TEST=' + + 480 + 720 + 29.970 + Progressive + BT.601 NTSC + BT.601 + +' + +STANDARD_PAL_ACCESS_DEINTERLACED_TEST=' + + 576 + 720 + 25.000 + Progressive + BT.601 PAL + BT.601 + +' + +AUDIO_CODEC_AAC_TEST=' + AAC + + 1 + 2 + + 48000 +' + + # define mediaconch test fragment -end _start_mediaconch_policy(){ @@ -2922,6 +2968,53 @@ _add_mediaconch_rule_set(){ fi } +_check_access_mp4_mediaconch() { + if [[ "${MP4_CHOICE}" = "true" ]] && [[ -f "${MP4NAME}" ]] && "${MEDIACONCH_INSTALLED}" ; then + _report -d "Checking access MP4 conformance against a mediaconch policy..." + MP4_POLICY_TMP="$(_maketemp .mediaconch_mp4.xml)" + cat < "${MP4_POLICY_TMP}" + + + This policy tests the access MP4 file made using vrecord and checks its validity against vrecord's access specifications +MC_MP4_START + echo "${CONTAINER_GENERAL_TEST}" >> "${MP4_POLICY_TMP}" + echo "${CONTAINER_MP4_TEST}" >> "${MP4_POLICY_TMP}" + echo "${CODEC_H264_TEST}" >> "${MP4_POLICY_TMP}" + if [[ "${STANDARD}" = "ntsc" ]] ; then + echo "${STANDARD_NTSC_ACCESS_DEINTERLACED_TEST}" >> "${MP4_POLICY_TMP}" + elif [[ "${STANDARD}" = "pal" ]] ; then + echo "${STANDARD_PAL_ACCESS_DEINTERLACED_TEST}" >> "${MP4_POLICY_TMP}" + fi + echo "${AUDIO_CODEC_AAC_TEST}" >> "${MP4_POLICY_TMP}" + cat <> "${MP4_POLICY_TMP}" + + +MC_MP4_END + MP4_REPORT_TMP="$(_maketemp _mediaconch_mp4report.xml)" + MP4_REPORT="${DIR}/${FULL_OUTPUT_ID}_mp4_mediaconch_report.xml" + MP4_POLICY="${DIR}/${FULL_OUTPUT_ID}_mp4_mediaconch_policy.xml" + mediaconch -fx -p "${MP4_POLICY_TMP}" "${MP4NAME}" | xmlstarlet fo > "${MP4_REPORT_TMP}" + MP4_STATUS="$(xmlstarlet sel -N mc="https://mediaarea.net/mediaconch" -t -v mc:MediaConch/mc:media/mc:policy/@outcome -n "${MP4_REPORT_TMP}")" + if [[ "${MP4_STATUS}" = "pass" ]] ; then + _report -dt "Access MP4 passed policy check." + _writeingestlog "mediaconch_mp4_outcome" "passed" + elif [[ "${MP4_STATUS}" = "fail" ]] ; then + _report -wt "The access MP4 file did not pass vrecord policy check." + _mv_tmp_file "${MP4_REPORT_TMP}" "${MP4_REPORT}" + _mv_tmp_file "${MP4_POLICY_TMP}" "${MP4_POLICY}" + _writeingestlog "mediaconch_mp4_outcome" "failed ${MP4_POLICY}" + _report -wt "See ${MP4_REPORT} for a full MediaConch policy report." + _report -wt "Or review this attempt to summarize the issue:" + xmlstarlet edit -N "mc=https://mediaarea.net/mediaconch" -d "//*[@outcome='pass']" "${MP4_REPORT}" | xmlstarlet fo + else + _report -wt "Mediaconch ended in an unexpected way for the access MP4 (status: ${MP4_STATUS})." + _report -wt "${MP4_REPORT_TMP}:" + cat "${MP4_REPORT_TMP}" + _writeingestlog "mediaconch_mp4_outcome" "error ${MP4_STATUS}" + fi + fi +} + _check_file_truncation() { TEST_FILE="${1}" TEST_LABEL="${2}" @@ -3573,11 +3666,11 @@ if [[ "${DEVICE_INPUT_CHOICE}" = 0 ]] ; then _writeingestlog "Decklink input buffer overrun" "Yes" fi - # policy checks with mediaconch + # mediaconch policy check on the preservation output if "${MEDIACONCH_INSTALLED}" ; then _report -d "Checking file conformance against a mediaconch policy..." - MEDIACONCH_REPORT="${DIR}/${FULL_OUTPUT_ID}_mediaconchreport.xml" - MEDIACONCH_REPORT_TMP="$(_maketemp _mediaconchreport.xml)" + MEDIACONCH_REPORT="${DIR}/${FULL_OUTPUT_ID}_mediaconch_report.xml" + MEDIACONCH_REPORT_TMP="$(_maketemp _mediaconch_report.xml)" MEDIACONCH_POLICY="${DIR}/${FULL_OUTPUT_ID}_mediaconch_policy.xml" mediaconch -fx -p "${MEDIACONCH_POLICY_TMP}" "${VRECORD_OUTPUT}" | xmlstarlet fo > "${MEDIACONCH_REPORT_TMP}" STATUS="$(xmlstarlet sel -N mc="https://mediaarea.net/mediaconch" -t -v mc:MediaConch/mc:media/mc:policy/@outcome -n "${MEDIACONCH_REPORT_TMP}")" @@ -3599,6 +3692,8 @@ if [[ "${DEVICE_INPUT_CHOICE}" = 0 ]] ; then _writeingestlog "mediaconch_outcome" "error ${STATUS}" fi fi + # mediaconch policy check on the access MP4 + _check_access_mp4_mediaconch # check file truncation _check_file_truncation "${VRECORD_OUTPUT}" "preservation"