Your camera delivers valid frames, the live preview runs, and the recording pipeline dies the moment the encoder element loads. The error names a device node rather than a codec setting, and that distinction decides the whole repair: either this SoC variant has no hardware video encoder, or its system image no longer matches one. Here you get the two-command check that settles which. You also get the arithmetic that says whether software encoding can absorb the stream, the bit rate and storage numbers a recording plan needs, and the controllers that take over recording when the embedded chip cannot. It is written for engineers recording from board-level cameras on embedded boards; every check runs from a terminal in under a minute.
Why does nvv4l2h265enc fail with "Could not open device /dev/nvhost-msenc"?
The error means the encoder element tried to open the platform's video-encoder device node and the kernel had nothing working behind it. Either the SoC variant has no hardware encoder block, or the running system image does not expose one. The camera is not the problem.
A typical failing pipeline hands hardware-memory frames straight to the encoder element:
nvarguscamerasrc ! 'video/x-raw(memory:NVMM),width=4032,height=3040,framerate=10/1,format=NV12' ! nvv4l2h265enc ! h265parse ! qtmux ! filesink location=demo.mp4
The element is a thin wrapper around the encode block in the SoC, and it opens the matching device node on your behalf. When the kernel has no working encoder behind that node, the open call fails and the pipeline never leaves the PAUSED transition - before a single frame is written. Three causes cover almost every occurrence, in order of probability:
- The SoC variant has no encoder block. Board families ship a lower-cost variant with the video encoder left out; it looks identical from outside the box.
- The installed image is stale or mismatched, so the node file exists but no driver services it.
- The GStreamer plugin cache is stale, or your user is not in the group that owns the node.
Valid frames from the sensor say nothing about the encode path, which is why capture and encode deserve separate tests. The general capture-and-save recipe is covered step by step in writing MP4 video from a camera on an embedded board.
How do you check whether the SoC has a hardware encoder at all?
Read the SoC identity and list the encoder device nodes before you build the pipeline; both checks take one command each. If the encoder node is absent from /dev, no GStreamer element can create it, and the decision is already made.
Two reads settle the silicon question - the first names the exact variant you are running, the second confirms it from the kernel's boot log:
cat /sys/devices/soc0/soc_id
sudo dmesg | grep "Machine model"
Variants within one board family differ in the encode block while sharing a case and a product label, so read the identity output instead of trusting the order code. Next, list the encoder nodes and look for the node your error named:
ls -lah /dev/nvhost-*
If that node is absent, the SoC has no hardware encoder. No element, permission or cache fix will create one - go straight to the fallback arithmetic below. If the node is present, prove the encode path with a synthetic source before the camera gets involved:
gst-launch-1.0 -e videotestsrc is-live=1 ! nvvidconv ! nvv4l2h265enc ! h265parse ! qtmux ! filesink location=a.mp4
A test-source encode that records cleanly proves block and plumbing together, so any remaining failure sits in the camera-side caps negotiation. You can check element presence without running anything using gst-inspect-1.0 nvv4l2h265enc.
Why does the encoder node show in ls but still refuse to open?
A node that appears in the listing yet refuses to open points at the system image rather than the silicon: a stale device tree or a stale plugin cache. In practice this one ends at a clean reflash and a cleared cache more often than at any pipeline edit.
A stale device tree - the hardware description carried inside the installed image - leaves the node file in /dev with no driver bound to it, and the open call then fails exactly as it would with no silicon at all. Work from the quickest fix to the slowest one. Clear the plugin cache first:
rm .cache/gstreamer-1.0/registry.aarch64.bin
Then reflash with the platform vendor's documented flashing tool, using the image release your camera driver was built against. An image that does not match its own hardware is what this symptom usually means, and the reflash is the fix that resolves it - not a pipeline edit.
Two smaller causes hide behind the same message. Check that the user running the recorder belongs to the group that owns the node; the listing shows root:video ownership with group read-write access, so video group membership decides who may open it. And confirm the element name exists on your release: the OMX-named encoders of older releases were removed and replaced by the V4L2-named element, so a launch string inherited from an older project can name an element that simply is not there any more.
Can software encoding keep up with a 12 MP stream?
Only if the pixel rate is small. The 4032x3040 NV12 stream at 10 fps hands the encoder 122.6 Mpixels/s, roughly twice the 62.2 Mpixels/s that a small embedded CPU cluster sustains at 1080p30 in software, so full-resolution software encoding will not keep up.
The raw rate the encoder is fed comes from one formula:
NV12 stores luma plus chroma subsampled by two in each direction, which is 12 bits - 1.5 bytes - per pixel. For the failing stream:
- 4032 x 3040 = 12,257,280 pixels per frame
- 12,257,280 x 1.5 B = 18,385,920 B, about 18.4 MB per frame
- 18,385,920 B x 10 fps = 183,859,200 B/s, about 184 MB/s or 1.47 Gbit/s
The software budget comes from the same arithmetic. A small embedded CPU cluster that sustains 1080p30 with a software H.264 encoder at a fast preset is processing 1920 x 1080 x 30 = 62.2 Mpixels/s. The 12 MP stream demands 12,257,280 x 10 = 122.6 Mpixels/s - almost exactly twice that. Encode time scales with pixel throughput, so the same cluster manages 62,208,000 px/s divided by 12,257,280 px/frame, or about 5 fps at full resolution.
So the decision is: full-resolution 12 MP recording at 10 fps requires the hardware encoder. Software encoding survives only if you give something up - record at 1920x1080 and the cluster holds 30 fps, or keep 4032x3040 and accept about 5 fps. A software encoder also cannot accept the hardware-memory caps the camera source exports, so add the platform converter (nvvidconv) and negotiate a system-memory raw format; the extra copy bills more CPU on top of the encode. If the same box runs detection, that load competes with inference - the mechanism behind high CPU usage with multiple cameras on one embedded board and why sustained recording FPS drops on an embedded vision box.
What bit rate and file size should the recording plan assume?
Start from bits per pixel per frame: H.265 at 0.1-0.2 bpp holds up for inspection review. For the 12 MP, 10 fps example that means 12 to 25 Mbit/s, a file growing at roughly 90 to 185 MB per minute.
Bits per pixel per frame is the planning number because it scales with resolution and frame rate together. Below 0.1 bpp, compression artifacts start eating the very edges you recorded to inspect. Applied to the 12 MP, 10 fps example:
- 12,257,280 px x 10 fps x 0.1 bit = 12.3 Mbit/s
- 12,257,280 px x 10 fps x 0.2 bit = 24.5 Mbit/s
At 15 Mbit/s, a sensible mid-point, the file grows at 15 / 8 = 1.875 MB/s - 112.5 MB per minute, 6.75 GB per hour. Against the raw 1.47 Gbit/s, an 18 Mbit/s encode is a reduction of roughly 80:1, and buying that reduction with silicon instead of CPU cycles is exactly what the hardware encoder is for.
At line-scan or high-frame-rate duty the same arithmetic outruns embedded storage quickly; the 2000 fps recording data-rate plan runs these numbers at a scale where storage choice decides the design. Once the encode path is proven, the application layer - codecs, container hygiene, open and close discipline - is covered in recording video from a machine vision camera in Python.
When should recording move to a vision controller instead?
Move recording off the embedded SoC when the same chip also runs detection. A stream that software-encodes at about 5 fps full resolution will also starve your inference loop, and a vision controller with a desktop-class CPU records from several cameras without touching that budget.
The trigger is contention, not outright failure. Three situations say move it:
- The SoC has no encoder block and you cannot accept about 5 fps at full resolution.
- The recording must run for hours unattended while inference, gauging or an operator interface keeps running on the same chip.
- More than one camera feeds the recorder and the pixel rates add up past the CPU cluster.
A vision controller is a fanless computer built around camera interfaces - several LAN ports, PoE options and built-in light channels - so capture wiring and encode CPU land in one box. The sizing logic behind a multi-camera recording host is laid out in selecting hardware for a multi-camera embedded video system.
For a multi-camera station that needs software-encode headroom, this controller pairs a desktop-class CPU with PoE camera ports:
- LAN ports
- 5+ LAN ports
- USB 3 ports
- 3-4 USB 3 ports
- PoE
- PoE camera ports
- Light outputs
- 8 built-in channels
Where storage decides the build, this model carries the hard drive:
- LAN ports
- 3-4 LAN ports
- USB 3 ports
- 2 USB 3 ports
- Light outputs
- 4 built-in channels
- Memory
- 8 GB
The MV-VC2140-128G40-1T records onto a 1 TB hard drive. At 15 Mbit/s that holds 8,000 Gbit divided by 15 Mbit/s, about 533,000 s - roughly 148 hours of continuous video - before anyone offloads it.
The three controllers below span the range from a compact recording node to a multi-camera station; compare them on LAN ports, memory and storage:
| Specification | MV-VC3301H-128G66 | MV-VC2140-128G40-1T | MV-VC5525-256G70-NN |
|---|---|---|---|
| CPU | Intel® Core i3-8100 | Intel® Processor N97 | Intel® Core i5-12400 |
| Memory | 8 GB | 8 GB | 32 GB |
| Storage | 128G SSD | 128 GB SSD + 1 TB HDD | 256 GB SSD |
| GPU | Intel® HD Graphics 630 | Intel® UHD Graphics | Intel® UHD Graphics 730 |
| Operating system | Windows 10 64-bit, Not activated | Unactivated 64-bit Windows 10 LTSC 21H2 | Unactivated Windows 10 |
| Encryption method | VM6200Pro license key | Not support | – |
| Video output | HDMI interface × 1, VGA interface × 1; Supports independent display output at the same time; Max. resolution 1920 × 1080 @ 60 Hz | HDMI interface × 1, VGA interface × 1; Supports independent display outputs at the same time; Max. resolution 1920 × 1080 @ 60 Hz | HDMI interface × 1, VGA interface × 1; Supports independent display output at the same time; Max. resolution 1920 × 1080 @ 60 Hz |
| Digital I/O | 8 digital isolated inputs supported; 16 opto-isolated outputs supported (NPN/PNP switchable) | Opto-isolated input × 8; Opto-isolated output × 8 | Opto-isolated input × 8; Opto-isolated output × 12 ( supports NPN/PNP switching), digital-isolated low-side driver output × 8; Non-isolated bi-directional differential I/O × 4 |
| Network interface | 6× Gigabit Ethernet ports | GigE interface × 4 | GigE interface × 7, including interface for PoE × 4 |
| USB Interface | USB 2.0 × 4; USB 3.0 × 4; Built-in USB 2.0 × 1 | USB 2.0 × 2; USB 3.0 × 2 | USB 2.0 × 4, USB 3.0 × 4, built-in USB 2.0 × 1 |
| Serial Port | 2× full-function RS-232, RS-485/RS-422 switchable | RS-232 × 1, supports switching to RS-485 or RS-422 | RS-232 × 2 by default, supports switching to RS-485 and RS-422 |
| Light interface | 4-channel 24 V constant-voltage light drive, Max. power per channel: 72 W, Max. power (4 channels): 150 W | Light interface with 24 VDC constant voltage × 4; (Brightness is adjustable. Max. current 3 A for single light interface, and total max. power consumption 80 W. Supports light mode switching between strobe and solid via external control) | 24 VDC constant voltage × 8; (Max. power consumption of single channel is 72 W, total max. power consumption 190 W) |
| Price | $2,419.00 | $1,679.00 | $4,479.00 · quoted |
All 3 share: Certification CE, KC. Values as printed in each product's data sheet; open a part for its drawing and full specifications.
The MV-VC3301H-128G66 sits at the compact end, pairing an Intel Core i3 with 8 GB of memory and 5+ LAN ports - enough for a small GigE recording station with software encoding of HD streams. Browse the rest of the vision controllers category once you know the camera count.
Which camera side keeps the pixel rate inside the encoder's budget?
Match the camera to the encoder's pixel budget instead of defaulting to the biggest sensor: width x height x fps is what the encoder bills, and dropping from 12 MP to 1.6 MP at the same 10 fps cuts the load from 122.6 to 16 Mpixels/s.
Sensor choice sets the encoder's load, so size the module to the recording duty rather than the largest sensor that fits. The same rule runs in reverse when you can still choose the sensor: resizing the module needs no reflash, no driver work and no new pipeline element.
The board-level cameras category exists for exactly this matching problem: compact modules you build the pixel budget around, with global shutters and M12 or C-mounts. For a global-shutter module in the up-to-3 MP class:
- Sensor format
- 1/2.9"
- Lens mount
- M12
- Interface
- GigE
- Resolution
- Up to 3 MP
The MV-CB016-10GM-M-W pairs an IMX296 sensor with a GigE interface, a global shutter and an M12 lens mount. Against a 12 MP module it presents the encoder with about an eighth of the pixel load at equal frame rates, which is the difference between a hardware requirement and a comfortable software path. Shortlist candidates by resolution, shutter and interface in the camera finder, then re-run the pixel-rate multiplication before you order.
How do you keep a missing encoder off the next build?
Settle the encoder question at specification time, before the board is ordered: name the SoC variant, confirm the encoder node exists on that variant, and prove the encode path with a test source at your resolution and frame rate.
Run the list at specification time, before a line of capture code exists:
- Name the SoC variant in the project notes. Save the output of the identity commands; variants inside one board family differ in the encode block, and the difference is invisible on the label.
- Prove the encode path with a test source. Run the synthetic-source pipeline at your target resolution and frame rate on the exact image release you will deploy.
- Budget bit rate and storage. Multiply pixels per frame by frame rate by bits per pixel; at 15 Mbit/s, plan 6.75 GB of storage per hour.
- Check permissions on the deployed image. The account the recorder runs under must belong to the group that owns the encoder node.
- Confirm the element name on your release. Encoder element names change between platform releases; an inherited launch string can name an element that no longer exists.
- Decide the fallback on day one. If the SoC lacks the block, choose now between reduced resolution, raw capture to a bigger recorder, or a vision controller - not during commissioning.
The same test-before-code discipline catches capture-side faults as well as encoder gaps; camera module raw image capture: check before you code applies it to the sensor side. More fault-finding guides of this kind are collected on the systems topic page, and if you want a pipeline checked before hardware is ordered, send the launch string and the identity output through the contact page - we will read the identity output and tell you whether that SoC carries an encoder.
Questions
Does a hardware encoder cost image quality compared with a software encoder?
At the same bit rate, yes, somewhat. A hardware block exposes far fewer tuning controls than a software encoder, so matching a software reference can take a larger file. Start from the bit rate your software encode needed, raise it until compression artifacts at the edges you inspect are gone, then lock that value into the pipeline so reviews stay consistent.
Should you record H.264 or H.265 from a machine vision camera?
Prefer H.265 whenever the hardware block offers it: at comparable quality it commonly needs 30-50% less bit rate than H.264, which roughly halves storage and network load for the same recordings. Choose H.264 only when playback or annotation tooling cannot decode H.265, and use an intra-only or MJPEG setting instead when reviewers need to scrub frame by frame.
Can you record raw frames now and encode them later on a bigger machine?
Yes, for short captures. The 12 MP, 10 fps NV12 example runs at 184 MB/s, which fills about 11 GB every minute, so you need storage rated well above that sustained write speed and sessions measured in minutes rather than hours. The payoff is an encode that costs nothing at capture time and full-quality source frames for tuning the encoder later.
The encoder works with a test source but fails with the camera - what now?
Then the encoder block is present and the failure is caps negotiation between the camera source and the encoder: pixel format, resolution or the hardware-memory caps the camera source exports. List the camera source's capabilities with gst-inspect-1.0, place the platform converter element between source and encoder, and test a reduced resolution first; if a lower resolution records, the limit is throughput, not wiring.
Do you still need the hardware encoder if you only stream live video?
In almost every case, yes. A compressed network stream uses the same encoder as the recording. Without it, raw video from the 12 MP example runs at 1.47 Gbit/s and will not traverse a GigE link, and JPEG-compressing every frame on a small CPU cluster costs more than the hardware encode it replaces. Stream H.265 from the hardware block and record from the same element.


