When using the camera.snapshot service on a Dahua camera (DH-IPC-HFW2449TL-S-PRO) entity configured with an 1440p H.265 main stream, the generated .jpg file contains an invalid JFIF header version. Specifically, the header injects JFIFVersion: 258 (hex: 0x0102), which does not exist in the official JPEG/JFIF specifications (only 1.00 and 1.01 are valid standards).
While common image viewers and web browsers are forgiving and ignore this bad marker, strict API engines such as the python-telegram-bot engine used by Home Assistant's Telegram integration reject the file completely, throwing an Image_process_failed error. This problem does not occur with snapshots of my dahua doorbell (DHI-VTO2202F-P-S2) H.264 720p
Reproduction Steps:
Configure a Dahua camera with H.265 encoding.
Trigger the camera.snapshot service via Home Assistant to save a frame locally (e.g., /config/www/snapshot.jpg).
Attempt to send this snapshot using the telegram_bot.send_photo action.
The action will fail with: Action failed. Image_process_failed.
(Note: Sending the exact same file using telegram_bot.send_document succeeds, proving paths and access rights are fine, but verifying the image processor engine rejects the byte payload).
Technical Metadata Analysis
A deep structural inspection of the generated snapshot file using a JPEG metadata validation bundle exposes the core parsing failure.
Parser Report Verdict:
piexifjs (JPEG-focused EXIF/JFIF parser): status: "error", detail: "Wrong JPEG data."
Extracted JFIF Section:
json
{
"section": "jfif",
"label": "JFIFVersion",
"keyPath": "JFIFVersion",
"values": [
"258"
]
}
Hex Header Signature:
ff d8 ff e0 00 10 4a 46 49 46 00 01 02 (where 01 02 explicitly reads as version 1.02 instead of standard 1.01 01 01).
Expected Behavior
The integration should encapsulate the pulled H.265 frame into a standard-compliant JPEG envelope mapping a valid web-safe specification version marker inside the APP0/JFIF block (e.g., hardcoding it to version 1.01 -> 0x0101 / 257), or completely omit the invalid version index entirely so external cloud processing hooks (like Telegram) do not drop the payload.
**Additional technical context to help locate the issue in the codebase:
The bug occurs during the encapsulation of the H.265 video frame into the JPEG container for the camera.snapshot service.
The integration/underlying streamer is manually constructing or passing an APP0 marker segment with an invalid version byte sequence:
ff d8 ff e0 00 10 4a 46 49 46 00 01 02 (JFIF v1.02)
To fix this structural error, the code needs to be updated to output standard-compliant JFIF version bytes:
ff d8 ff e0 00 10 4a 46 49 46 00 01 01 (JFIF v1.01)
This minor adjustment to the header generator will ensure full compatibility with strict image processing libraries (like piexifjs used by Telegram) without needing to alter the actual image payload or stream resolution.**
EXIFtool data:
Raw JSON Bundle
{
"name": "Voordeur_20260504_045938.jpg",
"ext": "jpg",
"mimeType": "image/jpeg",
"detectedMime": "image/jpeg",
"size": 612963,
"source": "file",
"url": "",
"signature": {
"ext": "jpg",
"mime": "image/jpeg",
"label": "JPEG (ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 01)"
},
"headHex": "ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 01",
"headHexLong": "ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 01 00 01 00 00 ff db 00 43 00 17 10 12 14 12 0f 17 14 13 14 1a 19 17 1c 23 3a 26 23 20 20 23 48 33 36 2a 3a 55 4a 59 58 53 4a 52 50 5d 69 86 72 5d",
"headText": "......JFIF.............C...............#:&# #H36*:UJYXSJRP]i.r]",
"headTextLong": "......JFIF.............C...............#:&# #H36*:UJYXSJRP]i.r]",
"hashes": {
"md5": "6deebcab106e55f590bab6524b501f75",
"sha1": "53c67ed633c04d516af8569a288065c89b38255b",
"sha256": "6679b3f202031af861c38fdc9b202c42bc04cc0c4ad1cdb28b4d0bc19e9a50a4",
"sha512": "0ade1a9d8308f3c44ae190f9bf18e8af83ea54faeb03d33ec46f3fc7076d01d066777a992f5c0c65cad2670d25e90e614111334629b52c17146e5337636caeaa",
"crc32": "b422b62d",
"adler32": "d550f2ee"
},
"relatedExts": [],
"viewer": {
"slug": "",
"via": "standalone",
"detectedMime": "image/jpeg"
},
"arrayBuffer": {},
"parserReports": [
{
"id": "exifr",
"label": "exifr",
"status": "success",
"note": "Broad parser for TIFF/EXIF, XMP, ICC, IPTC, JFIF, and IHDR.",
"detail": "Parsed structured metadata."
},
{
"id": "piexifjs",
"label": "piexifjs",
"status": "error",
"note": "JPEG-focused EXIF parser and fallback.",
"detail": "Wrong JPEG data."
},
{
"id": "pdf-metadata",
"label": "pdf metadata",
"status": "skipped",
"note": "PDF-specific metadata parser.",
"detail": "Skipped because the file is not PDF."
},
{
"id": "kamadak-exif",
"label": "kamadak-exif (WASM)",
"status": "skipped",
"note": "No browser-ready build is bundled in this repo. Adapter hook is available via window.EXIF_WASM_ADAPTERS.",
"detail": ""
},
{
"id": "rexif",
"label": "rexif (WASM)",
"status": "skipped",
"note": "No browser-ready build is bundled in this repo. Adapter hook is available via window.EXIF_WASM_ADAPTERS.",
"detail": ""
}
],
"metadata": [
{
"section": "jfif",
"label": "JFIFVersion",
"keyPath": "JFIFVersion",
"values": [
"258"
]
},
{
"section": "jfif",
"label": "Resolution Unit",
"keyPath": "ResolutionUnit",
"values": [
"0"
]
},
{
"section": "jfif",
"label": "Thumbnail Height",
"keyPath": "ThumbnailHeight",
"values": [
"0"
]
},
{
"section": "jfif",
"label": "Thumbnail Width",
"keyPath": "ThumbnailWidth",
"values": [
"0"
]
},
{
"section": "jfif",
"label": "XResolution",
"keyPath": "XResolution",
"values": [
"1"
]
},
{
"section": "jfif",
"label": "YResolution",
"keyPath": "YResolution",
"values": [
"1"
]
}
],
"parserResults": {
"exifr": {
"jfif": {
"JFIFVersion": 258,
"ResolutionUnit": 0,
"XResolution": 1,
"YResolution": 1,
"ThumbnailWidth": 0,
"ThumbnailHeight": 0
}
},
"piexifjs": null,
"pdf": null
},
"geoPoint": null
}
When using the camera.snapshot service on a Dahua camera (DH-IPC-HFW2449TL-S-PRO) entity configured with an 1440p H.265 main stream, the generated .jpg file contains an invalid JFIF header version. Specifically, the header injects JFIFVersion: 258 (hex: 0x0102), which does not exist in the official JPEG/JFIF specifications (only 1.00 and 1.01 are valid standards).
While common image viewers and web browsers are forgiving and ignore this bad marker, strict API engines such as the python-telegram-bot engine used by Home Assistant's Telegram integration reject the file completely, throwing an Image_process_failed error. This problem does not occur with snapshots of my dahua doorbell (DHI-VTO2202F-P-S2) H.264 720p
Reproduction Steps:
Technical Metadata Analysis
A deep structural inspection of the generated snapshot file using a JPEG metadata validation bundle exposes the core parsing failure.
Parser Report Verdict:
Extracted JFIF Section:
json
{
"section": "jfif",
"label": "JFIFVersion",
"keyPath": "JFIFVersion",
"values": [
"258"
]
}
Hex Header Signature:
ff d8 ff e0 00 10 4a 46 49 46 00 01 02 (where 01 02 explicitly reads as version 1.02 instead of standard 1.01 01 01).
Expected Behavior
The integration should encapsulate the pulled H.265 frame into a standard-compliant JPEG envelope mapping a valid web-safe specification version marker inside the APP0/JFIF block (e.g., hardcoding it to version 1.01 -> 0x0101 / 257), or completely omit the invalid version index entirely so external cloud processing hooks (like Telegram) do not drop the payload.
**Additional technical context to help locate the issue in the codebase:
The bug occurs during the encapsulation of the H.265 video frame into the JPEG container for the
camera.snapshotservice.The integration/underlying streamer is manually constructing or passing an APP0 marker segment with an invalid version byte sequence:
ff d8 ff e0 00 10 4a 46 49 46 00 01 02(JFIF v1.02)To fix this structural error, the code needs to be updated to output standard-compliant JFIF version bytes:
ff d8 ff e0 00 10 4a 46 49 46 00 01 01(JFIF v1.01)This minor adjustment to the header generator will ensure full compatibility with strict image processing libraries (like
piexifjsused by Telegram) without needing to alter the actual image payload or stream resolution.**EXIFtool data:
Raw JSON Bundle
{
"name": "Voordeur_20260504_045938.jpg",
"ext": "jpg",
"mimeType": "image/jpeg",
"detectedMime": "image/jpeg",
"size": 612963,
"source": "file",
"url": "",
"signature": {
"ext": "jpg",
"mime": "image/jpeg",
"label": "JPEG (ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 01)"
},
"headHex": "ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 01",
"headHexLong": "ff d8 ff e0 00 10 4a 46 49 46 00 01 02 00 00 01 00 01 00 00 ff db 00 43 00 17 10 12 14 12 0f 17 14 13 14 1a 19 17 1c 23 3a 26 23 20 20 23 48 33 36 2a 3a 55 4a 59 58 53 4a 52 50 5d 69 86 72 5d",
"headText": "......JFIF.............C...............#:&# #H36*:UJYXSJRP]i.r]",
"headTextLong": "......JFIF.............C...............#:&# #H36*:UJYXSJRP]i.r]",
"hashes": {
"md5": "6deebcab106e55f590bab6524b501f75",
"sha1": "53c67ed633c04d516af8569a288065c89b38255b",
"sha256": "6679b3f202031af861c38fdc9b202c42bc04cc0c4ad1cdb28b4d0bc19e9a50a4",
"sha512": "0ade1a9d8308f3c44ae190f9bf18e8af83ea54faeb03d33ec46f3fc7076d01d066777a992f5c0c65cad2670d25e90e614111334629b52c17146e5337636caeaa",
"crc32": "b422b62d",
"adler32": "d550f2ee"
},
"relatedExts": [],
"viewer": {
"slug": "",
"via": "standalone",
"detectedMime": "image/jpeg"
},
"arrayBuffer": {},
"parserReports": [
{
"id": "exifr",
"label": "exifr",
"status": "success",
"note": "Broad parser for TIFF/EXIF, XMP, ICC, IPTC, JFIF, and IHDR.",
"detail": "Parsed structured metadata."
},
{
"id": "piexifjs",
"label": "piexifjs",
"status": "error",
"note": "JPEG-focused EXIF parser and fallback.",
"detail": "Wrong JPEG data."
},
{
"id": "pdf-metadata",
"label": "pdf metadata",
"status": "skipped",
"note": "PDF-specific metadata parser.",
"detail": "Skipped because the file is not PDF."
},
{
"id": "kamadak-exif",
"label": "kamadak-exif (WASM)",
"status": "skipped",
"note": "No browser-ready build is bundled in this repo. Adapter hook is available via window.EXIF_WASM_ADAPTERS.",
"detail": ""
},
{
"id": "rexif",
"label": "rexif (WASM)",
"status": "skipped",
"note": "No browser-ready build is bundled in this repo. Adapter hook is available via window.EXIF_WASM_ADAPTERS.",
"detail": ""
}
],
"metadata": [
{
"section": "jfif",
"label": "JFIFVersion",
"keyPath": "JFIFVersion",
"values": [
"258"
]
},
{
"section": "jfif",
"label": "Resolution Unit",
"keyPath": "ResolutionUnit",
"values": [
"0"
]
},
{
"section": "jfif",
"label": "Thumbnail Height",
"keyPath": "ThumbnailHeight",
"values": [
"0"
]
},
{
"section": "jfif",
"label": "Thumbnail Width",
"keyPath": "ThumbnailWidth",
"values": [
"0"
]
},
{
"section": "jfif",
"label": "XResolution",
"keyPath": "XResolution",
"values": [
"1"
]
},
{
"section": "jfif",
"label": "YResolution",
"keyPath": "YResolution",
"values": [
"1"
]
}
],
"parserResults": {
"exifr": {
"jfif": {
"JFIFVersion": 258,
"ResolutionUnit": 0,
"XResolution": 1,
"YResolution": 1,
"ThumbnailWidth": 0,
"ThumbnailHeight": 0
}
},
"piexifjs": null,
"pdf": null
},
"geoPoint": null
}