Search by

1:1 PHP bindings of AVFoundation, AVKit, CoreMedia and CoreVideo, as classes and functions named after their native counterparts

Package info

github.com/php-io-extensions/avkit

Language:C

Type:php-ext

Ext name:ext-avkit

pkg:composer/php-io-extensions/avkit

Statistics

Installs: 0

Dependents: 0

Suggesters: 0

Stars: 0

Open Issues: 0

0.11.x-dev 2026-11-12 01:37 UTC

This package is auto-updated.

Last update: 2026-11-12 01:42:31 UTC


README

CI AVFoundation API

1:1 PHP bindings of AVFoundation, AVKit, CoreMedia and CoreVideo, as classes and functions named after their native counterparts. Version 0.11.2. macOS only.

A handle is one PHP object per native object, retained while PHP holds it. Requires ext-appkit 0.11.2: avkit's classes are appkit objects, AVPlayerView is an appkit NSView, and an NSURL, NSError, CGSize or CFTypeRef is appkit's NSURL, NSError, NSSize or CFType. An NSException becomes appkit's AppKitException.

Requirements

  • macOS
  • PHP 8.4, NTS or ZTS
  • ext-appkit 0.11.2, installed first (avkit compiles against its headers and loads after it)

Install

Through PIE:

pie install php-io-extensions/avkit

From a checkout of this repository:

./install-macos.sh

That builds into Homebrew php@8.4 and php@8.4-zts, ad-hoc signs the .so, and writes 30-avkit.ini. Pass other PHP binaries as arguments to install those instead.

Names

  • One PHP class per native class or CF type, one method per selector. Keywords are joined in camelCase: assetReaderTrackOutputWithTrack:outputSettings: is assetReaderTrackOutputWithTrackOutputSettings().
  • A C function is a global function under its C name: CMTimeMake(), CMSampleBufferGetImageBuffer(), CVPixelBufferGetBytesPerRow().
  • Enum cases are the C constant without its type prefix, in upper snake case: AVAssetReaderStatusCompleted is AVAssetReaderStatus::COMPLETED.
  • An NSDictionary argument (asset options, reader output settings) is a PHP array with string keys and string, int, float, bool or object values.
  • An NSError** is a by-reference ?NSError &$error in native position. A nil result is null.
  • A pixel address is an int (CVPixelBufferGetBaseAddress()), valid while the buffer is locked. CMBlockBufferCopyDataBytes() writes the bytes into its by-reference string when it returns 0.

What is bound

Framework Bound
AVFoundation AVAsset (duration, tracks, tracksWithMediaType:), AVURLAsset (URLAssetWithURL:options:, URL), AVAssetTrack (trackID, mediaType, naturalSize, nominalFrameRate, timeRange, formatDescriptions), AVAssetReader (assetReaderWithAsset:error:, asset, status, error, timeRange (+set), canAddOutput:, addOutput:, startReading, cancelReading), AVAssetReaderOutput (mediaType, alwaysCopiesSampleData (+set), copyNextSampleBuffer), AVAssetReaderTrackOutput (assetReaderTrackOutputWithTrack:outputSettings:, track), AVPlayerItem (playerItemWithURL:, status, duration, error), AVPlayer (playerWithPlayerItem:, play, pause, rate (+set), currentTime, seekToTime:, isMuted (+set), timeControlStatus, actionAtItemEnd (+set), currentItem, replaceCurrentItemWithPlayerItem:). Enums AVAssetReaderStatus, AVPlayerItemStatus, AVPlayerTimeControlStatus, AVPlayerActionAtItemEnd. Constants AVMediaTypeVideo, AVMediaTypeAudio, AVPlayerItemDidPlayToEndTimeNotification, AVFormatIDKey, AVSampleRateKey, AVNumberOfChannelsKey, AVLinearPCMBitDepthKey, AVLinearPCMIsFloatKey, AVLinearPCMIsBigEndianKey, AVLinearPCMIsNonInterleaved, kAudioFormatLinearPCM
AVKit AVPlayerView extends NSView (player (+set), controlsStyle (+set)), enum AVPlayerViewControlsStyle
CoreMedia CMTime, CMTimeRange, CMVideoDimensions, AudioStreamBasicDescription value classes; CMSampleBuffer, CMBlockBuffer, CMFormatDescription, CMVideoFormatDescription, CMAudioFormatDescription; CMTimeMake, CMTimeMakeWithSeconds, CMTimeGetSeconds, CMTimeCompare, CMTimeRangeMake, CMTimeRangeGetEnd, CMSampleBufferGetImageBuffer, CMSampleBufferGetDataBuffer, CMSampleBufferGetFormatDescription, CMSampleBufferGetPresentationTimeStamp, CMSampleBufferGetDuration, CMSampleBufferGetNumSamples, CMBlockBufferGetDataLength, CMBlockBufferCopyDataBytes, CMFormatDescriptionGetMediaType, CMVideoFormatDescriptionGetDimensions, CMAudioFormatDescriptionGetStreamBasicDescription; kCMTimeFlags_*, kCMMediaType_Video, kCMMediaType_Audio
CoreVideo CVBuffer, CVImageBuffer, CVPixelBuffer; CVPixelBufferLockBaseAddress, CVPixelBufferUnlockBaseAddress, CVPixelBufferGetBaseAddress, CVPixelBufferGetBytesPerRow, CVPixelBufferGetWidth, CVPixelBufferGetHeight, CVPixelBufferGetPixelFormatType, CVPixelBufferGetDataSize, CVPixelBufferIsPlanar, CVPixelBufferGetPlaneCount and the …OfPlane getters; kCVPixelBufferLock_ReadOnly, kCVPixelFormatType_32BGRA, kCVPixelBufferPixelFormatTypeKey

Coverage

SUPPORT.md lists every method and property accessor that the SDK's AVFoundation, AVKit, CoreMedia and CoreVideo headers declare on a class or category, and their AV, CM and CV C functions, not deprecated or unavailable on macOS, each marked bound or not; protocol methods (delegates) are not counted. The API badge is computed from it. Regenerate both after a binding change, and check them:

php84 scripts/support.php           # writes SUPPORT.md and the badge
php84 scripts/support.php --check   # exits 1 when either is stale

Example

Every frame of a movie as BGRA pixels, every audio chunk as 16-bit PCM:

$asset = AVURLAsset::URLAssetWithURLOptions(NSURL::fileURLWithPath('movie.mp4'), null);
$reader = AVAssetReader::assetReaderWithAssetError($asset, $error) ?? throw new RuntimeException($error->localizedDescription());
$video = AVAssetReaderTrackOutput::assetReaderTrackOutputWithTrackOutputSettings(
    $asset->tracksWithMediaType(AVMediaTypeVideo)[0],
    [kCVPixelBufferPixelFormatTypeKey => kCVPixelFormatType_32BGRA],
);
$audio = AVAssetReaderTrackOutput::assetReaderTrackOutputWithTrackOutputSettings(
    $asset->tracksWithMediaType(AVMediaTypeAudio)[0],
    [AVFormatIDKey => kAudioFormatLinearPCM, AVLinearPCMBitDepthKey => 16, AVLinearPCMIsFloatKey => false,
        AVLinearPCMIsBigEndianKey => false, AVLinearPCMIsNonInterleaved => false],
);
$reader->addOutput($video);
$reader->addOutput($audio);
$reader->startReading();

// One reader feeds both outputs: read them in turn so neither backs up behind the other.
do {
    if (($frame = $video->copyNextSampleBuffer()) !== null) {
        $pixels = CMSampleBufferGetImageBuffer($frame);
        CVPixelBufferLockBaseAddress($pixels, kCVPixelBufferLock_ReadOnly);
        $address = CVPixelBufferGetBaseAddress($pixels);   // BGRA, CVPixelBufferGetBytesPerRow() bytes a row
        CVPixelBufferUnlockBaseAddress($pixels, kCVPixelBufferLock_ReadOnly);
    }
    if (($chunk = $audio->copyNextSampleBuffer()) !== null) {
        $block = CMSampleBufferGetDataBuffer($chunk);
        CMBlockBufferCopyDataBytes($block, 0, CMBlockBufferGetDataLength($block), $pcm);
    }
} while ($frame !== null || $chunk !== null);

Test

composer install
php84 -d memory_limit=128M vendor/bin/pest
zhp -d memory_limit=128M vendor/bin/pest

License

MIT. See LICENSE.