PrismCore
FFmpeg démultiplexe, Apple lit.
La pile de lecture d’Apple fait des choses qu’aucun lecteur tiers ne peut faire — décodage matériel, Dolby Atmos en passthrough, Dolby Vision, Match Content. Simplement, elle n’ouvre pas un MKV. PrismCore remballe tout conteneur que libavformat sait lire en HLS-fMP4, le sert depuis un serveur en boucle locale et donne à un simple AVPlayer une URL de playlist. Le même fichier, le moteur d’Apple.
En production dans
Aether
Le moteur de lecture par défaut sur iPhone, iPad, Mac, Apple TV et Apple Vision Pro — actif à chaque installation, pas derrière un réglage.
C’est un package Swift, pas un framework à compiler. Tout ce qui donne déjà une URL à AVPlayer peut s’en servir.
Ce qui change quand vous lancez la lecture
PrismCore est fait pour être invisible : vous ouvrez un film, il se lance. Ce qu’il vous apporte, c’est précisément tout ce qu’un lecteur qui dessine sa propre image doit abandonner.
Votre ampli reçoit la vraie bande-son
Le Dolby Atmos quitte le fichier en bitstream et arrive en bitstream à l’ampli — jamais décodé, jamais aplati en route. L’ampli affiche Atmos parce qu’on lui donne vraiment de l’Atmos, pas une approximation stéréo.
Le téléviseur passe réellement en Dolby Vision
Sur l’Apple TV, la dalle est programmée avant le début de la lecture — fréquence d’images, plage dynamique, Dolby Vision — avec la même négociation que reçoivent les apps d’Apple. À un téléviseur qui refuse un master Dolby Vision, le film est proposé une seconde fois sans cette revendication : vous obtenez une image, pas une erreur.
C’est le lecteur que vous connaissez déjà
Menu des pistes, sous-titres, Picture in Picture, AirPlay, Match Content, avance avec la télécommande : tout cela est l’interface de lecture d’Apple, parce qu’en dessous c’est bel et bien le lecteur d’Apple.
Appareil froid, batterie tranquille
L’image est décodée par la puce vidéo dédiée et non par le processeur : une MKV coûte autant qu’un fichier pris en charge d’origine. Rien n’est transcodé — ni sur votre appareil, ni sur le serveur d’où vient le fichier.
Se déplacer reste instantané
Une carte du fichier entier est publiée avant que la première image ne soit servie : un saut au milieu d’un film de trois heures atterrit là et joue, au lieu de repréparer le film depuis le début. Et en faisant glisser la barre de lecture, vous voyez l’image que vous visez, même sur un fichier dont aucun serveur n’a jamais généré les vignettes.
Rien ne quitte votre appareil
Le remballage se fait sur l’appareil et est servi au lecteur via 127.0.0.1 — une adresse de boucle locale qui n’atteint jamais le réseau. Aucune étape dans le nuage, aucun compte, et rien sur ce que vous regardez qui puisse partir ailleurs.
L’astuce, en une image
MKV · MPEG-TS
Le conteneur qu’Apple n’ouvre pas
Démultiplexage
FFmpeg lit les pistes
HLS-fMP4
Remballé sur 127.0.0.1
AVPlayer
Le lecteur d’Apple lui-même
Vidéo · Audio · Sous-titres
Le fichier est lu, pas converti
Le démultiplexeur de FFmpeg ouvre le conteneur — MKV, MPEG-TS, AVI — et sépare son contenu en pistes : l’image, chaque langue audio, chaque sous-titre. Rien n’est décodé ni converti ; le fichier est seulement lu en morceaux.
Les pistes sont remballées intactes
La même image et le même son compressés sont placés dans des fragments MP4, décrits par une playlist du genre qu’AVPlayer ouvre nativement. C’est l’emballage qui change, pas le contenu — bit pour bit la même vidéo et le même audio que dans le fichier.
Une adresse locale les sert
Ces fragments sont remis à AVPlayer depuis 127.0.0.1, l’adresse qui ne quitte jamais l’appareil, comme si le film était diffusé en streaming. C’est toute l’astuce : le lecteur d’Apple diffuse volontiers ce qu’il refuse d’ouvrir comme fichier.
Le moteur d’Apple fait le reste
Décodage matériel, Atmos en passthrough, négociation Dolby Vision, menu des pistes, PiP et AirPlay — rien de tout cela n’est réécrit, car du point de vue d’AVPlayer il ne se passe rien d’inhabituel.
Deux choses ne peuvent pas être remballées et reçoivent leur propre traitement. Les sous-titres qui sont des images de texte plutôt que du texte (les PGS des remux Blu-ray) sont lus sur l’appareil par l’OCR de Vision et rejoignent les sous-titres ordinaires. Et une poignée de codecs qu’Apple ne décode pas du tout — VP9, MPEG-2, VC-1 — empruntent une seconde voie où PrismCore décode et dessine l’image lui-même : on y perd l’habillage du lecteur système, mais le film se lit.
Les questions qui reviennent
Est-ce que mes fichiers sont réencodés ?
Non. L’image et le son sont recopiés exactement tels qu’ils ont été lus — seule change la boîte dans laquelle ils se trouvent. Le fichier lui-même n’est pas modifié non plus : PrismCore ne fait que le lire.
Alors pourquoi AVPlayer n’ouvre-t-il pas une MKV tout seul ?
Apple fournit la prise en charge d’une liste fixe de conteneurs, et MKV n’y figure pas — même quand la vidéo et l’audio à l’intérieur sont des formats qu’Apple décode parfaitement. C’est un problème d’emballage, pas de décodage, et c’est précisément pourquoi remballer suffit à le régler.
Que devient l’audio TrueHD ou DTS ?
La pile d’Apple ne les accepte pas en bitstream : ils ne peuvent donc pas passer intacts. Plutôt que de les réduire en stéréo, PrismCore les convertit en EAC3 avec chaque canal à sa place — le surround reste du surround. La seule chose qui ne survit pas au trajet, c’est l’Atmos porté par du TrueHD ; l’Atmos en EAC3, celui que portent la plupart des remux, passe sans être touché.
Mon serveur Plex ou Jellyfin doit-il transcoder ?
Non, et c’est une bonne part de l’intérêt. Le serveur envoie le fichier d’origine et le remballage se fait sur votre appareil : pas de transcodage côté serveur pour faire fondre un NAS, et aucune qualité perdue au passage.
Peut-on le désactiver ?
Oui — Réglages ▸ Lecture dans Aether. Il est actif par défaut ; désactivé, la lecture retombe sur les autres moteurs exactement comme avant, pour cette installation, sans réinstallation ni réinitialisation.
La lecture démarre-t-elle plus lentement ?
Non. La source est ouverte une seule fois et seul son en-tête est lu : quelques dizaines de millisecondes sur un fichier local, environ un dixième de seconde sur le réseau — vous voyez « Préparation » à peu près aussi longtemps qu’avec un fichier qu’Apple ouvre directement.
Tout ce qui suit concerne l’intégration du moteur dans votre propre app. Si vous êtes venu en spectateur, vous avez déjà toute l’histoire — le reste, c’est de la plomberie.
Ce qu’il prend en charge
Conteneurs et codecs
Tout ce que libavformat sait lire — MKV, MPEG-TS, AVI. HEVC, H.264 et AV1 passent en copie de flux, avec AAC, AC3, EAC3, FLAC et ALAC. TrueHD, DTS, Opus et le reste passent par le pont audio et arrivent en EAC3 au lieu d’être aplatis. Une source anamorphique garde la forme que déclare son conteneur, dans la boîte pasp qu’AVPlayer respecte.
Du Dolby Atmos, pas un downmix
L’EAC3+JOC est copié intact et jamais décodé en PCM — et la boîte dec3 que FFmpeg perd lors d’une copie de flux est réinsérée : le seul signal qui pousse AVFoundation à prendre la voie Dolby plutôt que du DD+ ordinaire. Vérifié sur un ampli en HDMI.
Dolby Vision et HDR
Le Profile 5 garde son entrée dvh1, le Profile 7 devient du 8.1 monocouche via libdovi, et sur tvOS la dalle est programmée avant même qu’AVPlayer ne voie la playlist — la négociation doit précéder, sinon la variante est rejetée d’emblée. Un master refusé par un téléviseur est réessayé sans la revendication au lieu d’échouer.
Chaque piste, et chaque sous-titre
Chaque piste audio devient une rendition alternative avec son nom, sa langue et son nombre de canaux, si bien que le menu de pistes d’AVKit fonctionne tout seul. Les sous-titres texte deviennent du WebVTT segmenté qui survit au PiP et à AirPlay ; les PGS et VOBSUB ne portent que des images, ils sont donc lus sur l’appareil par l’OCR de Vision et rejoignent les renditions ordinaires — une piste ne fait rien tant qu’un lecteur ne la demande pas vraiment, ce qui rend gratuit un remux qui porte des dizaines de pistes PGS.
Naviguer comme dans un fichier local
Un plan de segments aligné sur les images clés est publié avant le premier paquet, et un saut hors de la fenêtre produite réancre le démultiplexeur à la demande. Un cache à budget d’octets limite le disque, pas la navigation — les segments évincés sont simplement reproduits, et un segment en cours de livraison n’est jamais celui qu’on évince. La production se cale environ une minute devant le dernier segment réellement récupéré par le lecteur, si bien qu’un fichier de plusieurs gigaoctets ne court jamais après son propre cache — et la lecture de la source se stabilise au vrai débit du film plutôt qu’à la vitesse de la ligne. Un conteneur sans index propre n’en reste pas là : la première lecture séquentielle récolte chaque image clé qu’elle lit et conserve la carte, si bien que la lecture suivante planifie dessus dès la première seconde. Cette même carte répond à SeekPreviewService, qui décode l’image clé couvrant n’importe quelle position en vignette pour la barre de lecture de l’hôte.
Une voie logicielle pour le reste
Les codecs qu’AVPlayer ne décode pas du tout — VP9, MPEG-2, VC-1 — passent par libavcodec vers un AVSampleBufferDisplayLayer, sans copie partout où VideoToolbox a un décodeur matériel. L’AV1 interroge le silicium réel, pas le nom de la puce, et les sources entrelacées avérées quittent la voie native pour le désentrelaceur — sur le GPU, sur les images que le décodeur a déjà produites, quand la build FFmpeg embarque ce filtre.
Un démarrage rapide
Une lecture ouvrait sa source deux fois — une fois pour la décision d’aiguillage de l’hôte, une fois pour produire — et sur le réseau cette seconde ouverture est un aller-retour au milieu de l’attente que l’utilisateur regarde. La sonde transmet désormais son contexte ouvert à la session, chaque ouverture ne lit que ce dont a besoin un conteneur qui se décrit lui-même, et les attentes internes se vérifient toutes les 10 ms au lieu de 100. Un remux HEVC/EAC3 de 5,4 Go en HTTP passe de la sonde à la playlist en 135 ms environ au lieu de 520 — et un fichier sans index de recherche, qu’il faudrait sinon parcourir une minute, démarre quand même, sur un plan borné.
Une licence compatible avec l’App Store
LGPL-2.1-or-later avec une Application Store Exception. Une app signée ne peut laisser personne la relier à nouveau, ce qui mettait la LGPL pure et la distribution en boutique en tension ; l’exception lève cette seule exigence pour les builds de boutique, tandis que les modifications de PrismCore lui-même restent en LGPL et doivent être publiées. L’API publique est stable depuis la 1.0 — une rupture signifie une version majeure, et chaque version est consignée dans le changelog.
Ce que ça change
Sur les plateformes Apple, on choisit d’ordinaire entre un lecteur qui garde le meilleur mais n’ouvre que les conteneurs d’Apple, et un autre qui ouvre tout mais dessine ses propres images et décode l’audio en PCM — c’est précisément là que meurent l’Atmos et le Dolby Vision. PrismCore n’est pas un lecteur : il alimente AVPlayer, il n’y a donc rien à sacrifier.
| PrismCore | AVPlayer | VLCKit | libmpv | |
|---|---|---|---|---|
| Lit les MKV, MPEG-TS, AVI | ||||
| Dolby Atmos transmis en bitstream | ||||
| Dolby Vision activé sur l’écran | ||||
| Match Content sur tvOS — fréquence et plage | ||||
| L’interface du lecteur d’Apple : pistes, PiP, AirPlay | ||||
| VP9, MPEG-2 et VC-1 |
VLCKit et libmpv dessinent dans leur propre couche et vous rendent du PCM : c’est pourquoi les lignes du milieu leur échappent — une conséquence de posséder le rendu, pas un oubli. AVPlayer échoue sur la première et la dernière ligne, car il n’accepte que les conteneurs pour lesquels Apple fournit le support.
Démarrer
Ajoutez le package, puis donnez-lui une URL. Un point d’entrée sonde la source et renvoie soit une playlist pour AVPlayer, soit un pipeline logiciel déjà démarré.
.package(url: "https://github.com/Wenzlik/PrismCore.git", from: "1.8.7")switch try await PrismCoreEngine.open(url: mkvURL) {
case .remux(let session, let playlist):
player.replaceCurrentItem(with: AVPlayerItem(url: playlist))
…
await session.stop()
case .software(let pipeline):
hostView.layer.addSublayer(pipeline.displayLayer!)
pipeline.play()
}Une fois la première lecture en place, deux options méritent le détour. Donnez un dossier de cache à la session et un conteneur sans index propre s’en constitue un pendant la lecture : la fois suivante, il se parcourt comme un fichier indexé. Ce même dossier alimente les vignettes de la barre de lecture, qui forment leur propre petit pipeline — contexte séparé, décodage sur le processeur, cache par image-clé — si bien qu’elles ne retardent jamais la lecture à laquelle elles appartiennent, quel que soit le moteur à l’écran.
let session = try PrismCoreSession(url: mkvURL, keyframeIndexCacheDirectory: caches)
let previews = SeekPreviewService(url: mkvURL, keyframeIndexCacheDirectory: caches)
let frame: CGImage = try await previews.thumbnail(at: 42 * 60)Les versions minimales sont iOS 16, tvOS 17, macOS 14 et visionOS 1. FFmpeg arrive via les xcframeworks dynamiques de MPVKit : un hôte qui embarque déjà MPVKit n’ajoute aucune dépendance binaire. Si votre CI résout les dépendances à votre place, épinglez une version exacte et gardez le Package.resolved commité au même niveau — sinon un build sur appareil et un build TestFlight tournent discrètement sur des moteurs différents.
Vous vouliez juste regarder quelque chose ?
C’était la moitié développeurs de la page. Si vous êtes ici pour regarder vos propres films et séries, PrismCore fait déjà son travail dans Aether — vous n’aurez jamais à y penser.
Découvrir AetherPrismCore est développé par Václav Zmrhal · zmrhal.cz