Open-source project
pion/mediadevices avatar
pion/mediadevices

pion/mediadevices: a Go MediaDevices API for cameras, microphones and screen capture

Go implementation of the MediaDevices API.

648 stars150 forksGoMIT

At a glance

What is it?
The library gives Go programs the same shape as the browser's getUserMedia, with device adapters and cgo codec bindings behind it. It is a good fit for server-side capture and WebRTC pipelines, and a poor fit if you wanted the browser API itself.
Who is it for?
Adopt pion/mediadevices if you are writing Go and need camera, microphone or screen capture feeding into WebRTC, RTP or an HTTP stream, and you accept cgo codec dependencies. Do not adopt it if you were looking for the browser's navigator.mediaDevices object, or if your target platform is outside Linux, macOS and Windows, since the README's input table lists only those three.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Go, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 29, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What pion/mediadevices actually solves

Go has no standard way to grab frames from a webcam. The os and image packages can decode and encode stills, but opening a V4L2 device on Linux, an AVFoundation capture session on macOS or a DirectShow source on Windows is platform work you would otherwise write three times. pion/mediadevices wraps those three backends behind one call, GetUserMedia, whose constraint struct deliberately mirrors the browser's MediaTrackConstraints.

The README states the intent plainly: the library "abstracts away the complexities of interacting with things like hardware and codecs". The audience is Go developers building video calls, RTP senders, MJPEG broadcasters or face-detection demos who do not want a browser in the loop. The repository's topics list audio-call, video-call, voip, livestream and p2p, which matches the examples directory: webrtc, rtp, http, archive, facedetection, openh264 and vnc.

If you arrived here looking for the JavaScript API, this is not it. Several of the related search phrases around navigator.mediaDevices belong to the browser specification, and this project is a separate Go implementation that borrows the naming. The distinction matters when you read the docs: there is no DOM, no permission prompt and no HTMLMediaElement here.

How GetUserMedia, drivers and the codec selector fit together

Three layers are visible from the repository layout. The first is the driver layer under pkg/driver. The README is explicit that "by default, there's no media input registered", and that you opt in with a blank import such as _ "github.com/pion/mediadevices/pkg/driver/camera". That side-effect import is what populates the device registry. A videotest driver exists as a dummy adapter for machines without hardware, and the README points at it in a comment.

The second layer is the stream and track API. GetUserMedia returns a stream, and stream.GetVideoTracks()[0] gives a track that you type-assert to *mediadevices.VideoTrack. From there NewReader(false) returns a reader whose Read method yields a frame plus a release function. The README explains why release exists: it returns the buffer "to hold frame back to the source so that the buffer can be reused for the next frames". Forgetting to call it is a resource leak, not a crash.

The third layer is encoding. Since the project does not implement codecs itself, it calls system libraries through cgo, and you declare what you want with mediadevices.NewCodecSelector and options such as WithVideoEncoders. The README declines to recommend one codec over another, calling the choice "very complex and can be subjective". That is honest, and it also means the selector is your problem to configure.

Installing pion/mediadevices and capturing your first frame

Installation is a single go get. The README gives this command, and nothing else is required for the core library:

bash
go get -u github.com/pion/mediadevices

A camera capture program then needs the camera driver registered as a side effect. The README's own snippet imports the camera package and, in a comment, the videotest package as a fallback when no camera is present. The frame that comes back is a standard image.Image, so jpeg.Encode from the standard library can write it straight to disk as frame.jpg.

go
import (
	"github.com/pion/mediadevices"
	"github.com/pion/mediadevices/pkg/prop"
	_ "github.com/pion/mediadevices/pkg/driver/camera"
)

stream, _ := mediadevices.GetUserMedia(mediadevices.MediaStreamConstraints{
	Video: func(constraint *mediadevices.MediaTrackConstraints) {
		constraint.Width = prop.Int(600)
		constraint.Height = prop.Int(400)
	},
})

If you want H.264 output rather than raw frames, the codec layer needs a system library first. The README lists brew install x264 on macOS and apt install libx264-dev on Ubuntu. After that, the x264 package is configured with parameters and handed to the selector:

go
x264Params, _ := x264.NewParams()
x264Params.Preset = x264.PresetMedium
x264Params.BitRate = 1_000_000 // 1mbps

codecSelector := mediadevices.NewCodecSelector(
	mediadevices.WithVideoEncoders(&x264Params),
)

On machines where the malgo microphone dependency cannot be built, the README documents a nomicrophone build tag for cross-compilation. Build with go build -tags nomicrophone and the audio path is dropped.

The cgo and build tag costs you inherit

The library is not pure Go. The README states that because codecs are not implemented in the project, it "needs to call the codec libraries from the system through cgo", and that you must install those libraries before use. That has consequences the README does not spell out: a CGO_ENABLED=0 build cannot use the codec packages at all, and cross-compiling to a different OS or architecture means cross-compiling the codec too.

The Makefile shows how seriously the project takes that problem. It defines dockerfiles and a scripts/cross toolchain path, a supported_platforms list of linux-armv7, linux-arm64, linux-x64, windows-x64, darwin-x64 and darwin-arm64, and per-codec build targets such as make build-opus-darwin-x64 driven by MEDIADEVICES_TOOLCHAIN_BIN and MEDIADEVICES_TARGET_PLATFORM variables. That is a container-based cross-build system for codec dependencies, and adopting it means adopting Docker in your release pipeline.

There is also a platform boundary. The README's input table covers Camera, Microphone and Screen across Linux, Mac and Windows only. Nothing there suggests support for Android, iOS or a BSD. The mmal codec is described as H264 hardware encoding for Raspberry Pi and VideoCore boards, and the README says it needs no installation because it comes built in, which is the one codec path that does not pull a system library.

pion/mediadevices versus GStreamer or FFmpeg bindings

The obvious alternative in Go is to drive GStreamer or FFmpeg through their C libraries, either with go-gst or by wrapping libavcodec directly. The difference is where the abstraction sits. GStreamer models a pipeline of elements you construct and link; FFmpeg gives you format contexts and codec contexts you feed packets through. Both expose far more of the media stack, including container muxing, filters and a much longer codec list.

pion/mediadevices instead models the browser surface: constraints in, tracks out, a reader that hands you decoded frames. That is a smaller vocabulary, and it is deliberately shaped so the output plugs into pion/webrtc, which is a direct dependency in go.mod alongside pion/rtp, pion/rtcp and pion/interceptor. If your end goal is a WebRTC track or an RTP packet stream, the glue is already written. If your end goal is transcoding a file or building a filter graph, this library is the wrong shape and GStreamer will fit better.

The trade-off is control. The codec selector exposes per-codec parameter structs such as x264Params.Preset and x264Params.BitRate, which is enough for bitrate and preset tuning, but there is no pipeline graph to insert a scaler or a custom filter into. Frame-level work happens in your Go code after Read returns.

Maintenance, licence and upgrade surface

The repository is not archived, and the last push was on 2026-09-07. The most recent tagged release listed is v0.10.0 from 2026-04-21, preceded by v0.9.4 on 2026-02-05 and v0.9.3 on 2026-02-04, so releases arrive in bursts rather than on a schedule. The presence of renovate.json suggests dependency updates are automated, and go.mod pins a broad dependency tree including pion/webrtc/v4 v4.2.20 and pion/rtp v1.10.5.

The version number is still below 1.0, which is the honest signal about API stability: the pre-1.0 convention is that minor releases may break things, and v0.9.3 to v0.9.4 to v0.10.0 is exactly that pattern. Pin a version in go.mod rather than tracking main if you ship binaries.

The licence is MIT, as stated in the README badge and the LICENSE file. MIT is permissive and imposes no copyleft on your own code. That said, the codec libraries you install separately carry their own licences, and x264 in particular is a separate project with its own terms. Check those independently; the MIT grant here covers this repository, not the system libraries it links against.

Editorial conclusion

Adopt pion/mediadevices if you are writing Go and need camera, microphone or screen capture feeding into WebRTC, RTP or an HTTP stream, and you accept cgo codec dependencies. Do not adopt it if you were looking for the browser's navigator.mediaDevices object, or if your target platform is outside Linux, macOS and Windows, since the README's input table lists only those three. Verify before committing: that libx264 or your chosen codec library is installable on every build machine, that a CGO_ENABLED=0 build with -tags nomicrophone still compiles your package set, and that the dummy videotest adapter can stand in for real hardware in CI.

Frequently asked questions

What is the pion/mediadevices API?

It is a Go implementation of the browser MediaDevices API. The README states that it provides access to media input devices like cameras, microphones and screen capture, and can encode the resulting video or audio stream to various codec selections.

How do I use pion/mediadevices to access a webcam from Go?

Import the camera driver package as a side effect, then call mediadevices.GetUserMedia with a MediaStreamConstraints value. The README's example sets constraint.Width and constraint.Height, takes stream.GetVideoTracks()[0], and reads frames through videoTrack.NewReader(false).

Why is navigator.mediaDevices undefined, and does pion/mediadevices fix that?

pion/mediadevices is a Go library and does not run in a browser, so it has no bearing on navigator.mediaDevices being undefined in a page. The README describes a Go API with GetUserMedia, tracks and codec selectors, not a JavaScript shim.

What is getUserMedia in pion/mediadevices?

It is the entry point of the Go API, mirroring the browser function of the same name. The README's examples pass it a MediaStreamConstraints value describing the video constraints and, optionally, a codec selector built with mediadevices.NewCodecSelector.

What are media devices in the context of pion/mediadevices?

The README describes them as media input devices: cameras, microphones and screen capture. The Available Media Inputs table lists those three and marks them as supported on Linux, Mac and Windows.

What is navigator.mediaDevices compared to pion/mediadevices?

navigator.mediaDevices is the browser object from the specification this project takes its name and API shape from. pion/mediadevices is a Go library that reimplements that surface for server-side and native programs, with driver packages and cgo codec bindings instead of browser permissions.

Official sources

  1. License: MIT
  2. pion/mediadevices on GitHub
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/pion-mediadevices.svg)](https://hysenlabs.com/projects/pion-mediadevices)