Open-source project
danielpaulus/quicktime_video_hack avatar
danielpaulus/quicktime_video_hack

quicktime_video_hack speaks Apple's QuickTime screensharing protocol to record iOS devices

Record iOS device audio and video

639 stars128 forksGoMIT

At a glance

What is it?
quicktime_video_hack, or qvh, is a Go implementation of the protocol macOS QuickTime uses to mirror an iPhone or iPad over USB, so you can capture raw H264 video and wave audio from a device without a Mac and without QuickTime Player. It also offers a Gstreamer path for transcoding, and the author states plainly that Windows support was abandoned.
Who is it for?
Adopt quicktime_video_hack if you need to capture screen and audio from iOS devices on Linux or macOS, particularly in a lab, test rig or CI environment where a Mac with QuickTime Player is not available, and if you are comfortable working at the USB protocol level. Do not adopt it for Windows, since the author has given up on that and states he did not find a way to do it, and do not adopt it as a general screen recording tool, since it is specific to iOS devices over USB.
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 147 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 October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What qvh replaces and why it exists

quicktime_video_hack is an operating system independent implementation of QuickTime screensharing for iOS devices, and the README states the motivation directly: the repository contains all the code needed to grab and record video and audio from one or more iPhones or iPads without needing one of the expensive macOS computers or the hard to use QuickTime Player.

That framing is important, because it identifies the tool as a protocol implementation rather than a recorder. On macOS, mirroring an iPhone screen to a Mac is done by a private Apple framework, com.apple.cmio.iOSScreenCaptureAssistant, driven from QuickTime. The README says qvh probably does something similar to what QuickTime and that framework are doing, and the author has written technical documentation for the protocol in doc/technical_documentation.md for anyone who wants to reimplement it in a different language than Go.

The audience is therefore two groups. The first is people who need the capture itself, in a lab, a test rig, a CI job or a broadcast setup where a Mac is not an option. The second is protocol implementers, and the README supports them with two things: the technical documentation and extracted binary dumps of all messages, for writing unit tests and reimplementing the protocol in a test driven style.

The primary language is Go, the module is github.com/danielpaulus/quicktime_video_hack, and the licence is MIT. The top level of the repository is small and readable: main.go, a screencapture directory holding the implementation, a doc directory, a docker directory, a log directory and a go.mod.

The most recent release tag listed is v0.5-beta, described as macOS stability fixes and a new audio command, dated 2020-09-13, with v0.2-beta and v0.1-alpha before it. The last push was on 2026-05-29, and the repository is not archived.

Three output paths: raw capture, Gstreamer, audio only

The usage section describes a command line with a few distinct modes, and the mode you pick determines what the tool does and what you have to install.

For just displaying the screen, the command is qvh gstreamer, and the README says it will work. For raw media output without Gstreamer involved, the command is qvh record out.h264 out.wav, which writes the video and the audio as separate elementary streams. The README lists the raw formats as H264 and wave audio in the Apple demonstration mode, where the device shows the 9:41am screen, a full battery and no carrier in the status bar, which is what makes a clean capture possible.

The audio-only path is separate and, according to the README, no longer requires the demonstration mode. You can grab device audio as wave, ogg or mp3, with qvh audio out.wav --wav for wave, qvh audio out.mp3 --mp3 and qvh audio out.ogg --ogg for the compressed formats. The README marks that capability with a celebratory note, which suggests it was a long requested feature.

The Gstreamer path is the flexible one. You can use custom Gstreamer pipelines to transcode the AV data into whatever you like, and qvh gstreamer --examples shows the transcoding and streaming options.

There is also a diagnostics command that is more interesting than it sounds: qvh diagnostics metrics.csv --dump=binary.bin persists logs to a file, dumps all USB transfers and gathers metrics. For a tool that talks to a device over an undocumented protocol, having a mode that records the raw USB traffic is what makes a failure debuggable at all.

The protocol side, and the dependencies that come with it

The dependency list in go.mod tells you what the implementation leans on, and it is worth reading before you install anything.

Two dependencies are the author's own work. github.com/danielpaulus/go-ios provides the device side, which is the part that talks to the iOS device over USB, and github.com/danielpaulus/gst provides the Gstreamer bindings, which is why the glib dependency is there too through github.com/lijo-jose/glib. The USB layer itself is github.com/google/gousb, so this is libusb under the hood, and the command line parsing is github.com/docopt/docopt-go, which is why the usage section reads like a set of example invocations rather than a flag reference.

The logging is logrus, the errors are wrapped with github.com/pkg/errors, and the tests use testify.

The Go version declared is 1.16, which tells you the age of the codebase, and it matches the release timeline rather than the 2026 push date. The require block from the module file shows the direct dependencies as they are recorded:

toml
require (
	github.com/danielpaulus/go-ios v1.0.13
	github.com/danielpaulus/gst v0.0.0-20200201205042-e6d2974fceb8
	github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815
	github.com/google/gousb v2.1.0+incompatible
)

Installation on macOS is a Homebrew line for the native libraries:

The brew line the README gives installs libusb, pkg-config and the four Gstreamer plugin sets, bad, good, base and ugly, and it is reproduced here as prose rather than as a copyable block because the README presents it inline in its numbered list.

On Linux there are two paths. The first is Docker, and the README points at a docker directory in the repository with one file for just building and one for running. The second is local, where the README asks you to copy the dependencies from the Debian Dockerfile and install them with apt.

The Gstreamer plugin set is the interesting part of that list. You need base, good, bad and ugly, which is close to everything, and that is a hint about how much of the pipeline the tool expects to have available for decoding and encoding.

Release 0.6 notes and the state of the project

The README opens with a section headed Release 0.6, and it reads like a status update from someone who is candid about the remaining work rather than a release announcement.

The first point is that qvh without Gstreamer is finally stable on macOS, and the supporting detail is specific: the author ran it for 16 hours straight on parallel devices and it worked flawlessly. That is a claim about the raw capture path, and it is the path the author considers the reliable one.

The second point sets the next milestone: before a 1.0 release, the author needs to see whether Gstreamer is stable enough, and maybe to fix it or switch to ffmpeg. The mention of ffmpeg as a possible replacement for Gstreamer is significant, because Gstreamer is the heaviest dependency in the list and the one that is preventing a stable 1.0.

The third point is that Linux support needs to be improved, and the phrasing is that it works but it is hard to get going currently. The Docker files exist precisely to make that easier.

And then the instruction to create an issue if you miss anything.

So the honest reading of the project state is: the raw capture path is solid, the Gstreamer transcoding path is unproven, Linux is workable but rough, and the maintainer is candid about all three. The releases listed confirm the pattern, with a v0.5-beta focused on macOS stability fixes and a new audio command, a v0.2-beta that added working Gstreamer for AV playback, and a v0.1-alpha with recording files.

The last push on 2026-05-29 shows the repository still receives changes, but no 1.0 release is listed and the newest tag remains a beta from 2020.

Windows is out, and that is a real constraint

The README has a line that deserves more attention than it gets: I have given up on windows support, followed by a struck-through Port to Windows link and the parenthetical Did not find a way to do it.

The tone is the author's own, with the aside that people still use Windows nowadays, and the reason given is simply that there was no way to do it. The cause is not hard to infer from the dependency list, since the USB access goes through libusb, and a libusb-based implementation on Windows means dealing with the WinUSB driver installation and the device driver model rather than the straightforward Unix path.

For an adopter this is a hard constraint, not a caveat. The tool supports macOS and Linux, and the README's own release notes confirm that Linux support is the rougher of the two. A team on Windows has to run it in a Linux VM or a container, which for a tool whose whole point is direct USB access to a physical device is an awkward fit, since the USB device has to be passed through to the guest.

The same reasoning applies to the Docker route on Linux. The Docker files are the recommended path there, and a container that needs raw USB access to an iPhone needs the device passed in, which is exactly the configuration that is easy on Linux and awkward elsewhere.

The author has also left the door open for other languages. The technical documentation and the extracted binary dumps of all messages are published so that a Windows implementation, or an implementation in a language with better Windows USB support, is a documented project rather than an archaeology exercise.

Where qvh is the wrong tool

Three cases, and the first is the most likely to bite.

The first is that this is an iOS device capture tool, not a screen recorder. It records from iPhones and iPads over USB. It does not record your desktop, it does not record an Android phone, and it does not record a browser tab. If the requirement is capturing a phone screen, the platform is not iOS, or the capture is of a display rather than a device, then this is the wrong project and the QuickTime or an OS level recorder is.

The second is that the protocol is reverse engineered and therefore version sensitive. The README frames the tool as similar to what QuickTime and the iOSScreenCaptureAssistant do, which means it is built from observation of Apple's behaviour rather than from a published specification. A new iOS release can change the message set, and when it does, the failure mode is a capture that stops working rather than an error message that names the cause. The diagnostics mode with binary dumps exists precisely because of this, and the protocol documentation for reimplementers is the other half of the same answer. Anyone adopting the tool should plan to keep the binary dumps and be ready to read the protocol documentation.

The third is the Gstreamer dependency. The raw capture path is proven and needs no Gstreamer at all, but anything that transcodes or streams depends on a large plugin stack, and the maintainer himself lists Gstreamer stability as the open question blocking 1.0, with a possible switch to ffmpeg on the table. If you need a stable, supported transcoding pipeline today, the raw path plus an external ffmpeg invocation gives you the same result with a dependency you already understand.

The alternative approach, for completeness, is the official one. A Mac with QuickTime Player and a Lightning or USB-C cable does this natively, and it is the path Apple supports. The difference in approach is that qvh reimplements an undocumented protocol on the host side, which is why it can run on Linux and in CI, and also why it is the more fragile option when Apple changes something.

Editorial conclusion

Adopt quicktime_video_hack if you need to capture screen and audio from iOS devices on Linux or macOS, particularly in a lab, test rig or CI environment where a Mac with QuickTime Player is not available, and if you are comfortable working at the USB protocol level. Do not adopt it for Windows, since the author has given up on that and states he did not find a way to do it, and do not adopt it as a general screen recording tool, since it is specific to iOS devices over USB. Verify first that you can install libusb and the Gstreamer packages or run the Docker files, that your device is a USB-connected iPhone or iPad rather than a network target, and that your iOS version still works with the implementation, since the Release 0.6 notes leave Gstreamer stability and a possible switch to ffmpeg open.

Frequently asked questions

What does quicktime_video_hack do?

It is an operating system independent implementation of QuickTime screensharing for iOS devices, in Go. It records video and audio from one or more iPhones or iPads over USB without needing a macOS machine or QuickTime Player, producing raw H264 and wave audio, or feeding a Gstreamer pipeline.

How do I install quicktime_video_hack on macOS?

Run brew install libusb pkg-config gstreamer gst-plugins-bad gst-plugins-good gst-plugins-base gst-plugins-ugly, then either download the latest release and run it, or clone the repo and execute go run main.go if you have Go installed.

Does quicktime_video_hack support Windows?

No. The README says the author has given up on Windows support and did not find a way to do it, with a struck-through port to Windows link. The project supports macOS and Linux, and the release notes say Linux works but is hard to get going.

How do I record audio only from an iOS device with qvh?

Use the audio command with a format flag, for example qvh audio out.wav --wav for wave, qvh audio out.mp3 --mp3 or qvh audio out.ogg --ogg. The README states that device audio can be grabbed as wave, ogg or mp3 without the Apple demonstration mode.

How do I debug a failed capture with qvh?

Run qvh diagnostics metrics.csv --dump=binary.bin, which persists logs to a file, dumps all USB transfers and gathers metrics. The README also documents a technical write-up and extracted binary dumps of all messages so the protocol can be reimplemented or unit tested.

Official sources

  1. danielpaulus/quicktime_video_hack on GitHub
  2. Issues
  3. License: MIT
  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/danielpaulus-quicktime-video-hack.svg)](https://hysenlabs.com/projects/danielpaulus-quicktime-video-hack)

Was this useful?