{"slug": "detect-ai-generated-images-audio-and-text-with-open-source-models", "title": "Detect AI-Generated Images, Audio, and Text with Open-Source Models", "summary": "A new tutorial by Emeka Okafor demonstrates building a local Python pipeline that uses three open-source Hugging Face classifiers to detect AI-generated images, audio, and text, emitting a JSON verdict and exit code to gate uploads. The models include Organika/sdxl-detector for images (98% validation accuracy, CC-BY-NC-3.0), MelodyMachine/Deepfake-audio-detection-V2 for audio (99.7% accuracy, Apache-2.0), and fakespot-ai/roberta-base-ai-text-detection-v1 for text (Apache-2.0). The pipeline runs on CPU, requires Python 3.10+, transformers 5.15.0, PyTorch 2.13.0, and about 2 GB disk space, with a caution that detector scores are risk signals, not ground truth.", "body_md": "# Detect AI-Generated Images, Audio, and Text with Open-Source Models\n\nWire three Hugging Face classifiers into one local pipeline that flags synthetic media before it reaches users.\n\n[Emeka Okafor](https://sourcefeed.dev/u/emeka_okafor)\n\n## What you'll build\n\nA local Python pipeline that routes incoming files to three open-source classifiers — one each for images, audio, and text — and emits a JSON verdict (`synthetic`\n\nor `authentic`\n\n) plus a non-zero exit code you can use to gate uploads before they reach your users.\n\n## Prerequisites\n\n- Python 3.10+ (verified with 3.12;\n[Transformers](https://huggingface.co/docs/transformers)v5 requires ≥3.10) `transformers`\n\n5.15.0,[PyTorch](https://pytorch.org)2.13.0 (Transformers v5 needs torch ≥2.5), Pillow[FFmpeg](https://ffmpeg.org)on your PATH — the audio pipeline shells out to it to decode files- ~2 GB free disk: the three model checkpoints total roughly 1.2 GB on first download\n- No GPU required. Everything here runs on CPU; a GPU just makes it faster.\n- macOS or Linux assumed for shell commands; everything works on Windows with the usual venv path changes\n\n## 1. Set up the environment\n\n```\nmkdir synthetic-gate && cd synthetic-gate\npython3 -m venv .venv && source .venv/bin/activate\npip install \"transformers==5.15.0\" torch pillow\n```\n\nInstall FFmpeg if you don't have it:\n\n```\n# macOS\nbrew install ffmpeg\n# Debian/Ubuntu\nsudo apt-get install -y ffmpeg\n```\n\n## 2. Meet the three classifiers\n\nYou want one battle-tested checkpoint per modality, all loadable through the same `pipeline()`\n\nAPI so the routing code stays trivial:\n\n**Images:**— a Swin transformer fine-tuned on Wikimedia-vs-SDXL image pairs, ~98% validation accuracy. Labels:`Organika/sdxl-detector`\n\n`artificial`\n\n/`human`\n\n. Heads up: it's licensed CC-BY-NC-3.0, so it's fine for evaluation and internal research but not commercial deployment — for that, swap in the Apache-2.0(EfficientNet-B4, loads via`Dafilab/ai-image-detector`\n\n`timm`\n\ninstead of`pipeline`\n\n).**Audio:**— wav2vec2-base fine-tuned for spoofed-voice detection, 99.7% accuracy on its eval set, Apache-2.0. Labels:`MelodyMachine/Deepfake-audio-detection-V2`\n\n`fake`\n\n/`real`\n\n. Expects 16 kHz input; the pipeline resamples for you when FFmpeg decodes the file.**Text:**— a RoBERTa-base classifier from Fakespot (Mozilla) for English text, Apache-2.0. Labels:`fakespot-ai/roberta-base-ai-text-detection-v1`\n\n`Human`\n\n/`AI`\n\n. RoBERTa caps at 512 tokens, so longer inputs must be truncated or chunked.\n\nOne thing to internalize before shipping any of this: detector scores are risk signals, not ground truth. All three models were trained against specific generator families, and accuracy drops on generators released after training, on heavily compressed re-uploads, and on out-of-domain content. Route high scores to a human review queue; don't auto-ban on them.\n\n## 3. Write the routing pipeline\n\nSave this as `detect.py`\n\n:\n\n``` python\nimport json\nimport sys\nfrom pathlib import Path\n\nfrom transformers import pipeline\n\nMODELS = {\n    \"image\": (\"image-classification\", \"Organika/sdxl-detector\"),\n    \"audio\": (\"audio-classification\", \"MelodyMachine/Deepfake-audio-detection-V2\"),\n    \"text\": (\"text-classification\", \"fakespot-ai/roberta-base-ai-text-detection-v1\"),\n}\n\nEXTENSIONS = {\n    \".jpg\": \"image\", \".jpeg\": \"image\", \".png\": \"image\", \".webp\": \"image\",\n    \".wav\": \"audio\", \".mp3\": \"audio\", \".flac\": \"audio\", \".m4a\": \"audio\",\n    \".txt\": \"text\", \".md\": \"text\",\n}\n\n# Each model names its labels differently; anything in this set means \"machine-made\".\nSYNTHETIC = {\"artificial\", \"fake\", \"AI\"}\n\n_pipes = {}\n\ndef get_pipe(modality):\n    if modality not in _pipes:\n        task, model = MODELS[modality]\n        _pipes[modality] = pipeline(task, model=model)\n    return _pipes[modality]\n\ndef detect(path: Path) -> dict:\n    modality = EXTENSIONS.get(path.suffix.lower())\n    if modality is None:\n        raise SystemExit(f\"unsupported extension: {path.suffix}\")\n    pipe = get_pipe(modality)\n    if modality == \"text\":\n        # truncation is forwarded to the tokenizer; RoBERTa can't take >512 tokens\n        scores = pipe(path.read_text(encoding=\"utf-8\"), truncation=True, top_k=None)\n    else:\n        scores = pipe(str(path))\n    best = max(scores, key=lambda s: s[\"score\"])\n    return {\n        \"file\": path.name,\n        \"modality\": modality,\n        \"verdict\": \"synthetic\" if best[\"label\"] in SYNTHETIC else \"authentic\",\n        \"label\": best[\"label\"],\n        \"score\": round(best[\"score\"], 4),\n        \"model\": MODELS[modality][1],\n    }\n\ndef main():\n    results = [detect(Path(p)) for p in sys.argv[1:]]\n    print(json.dumps(results, indent=2))\n    # exit 1 if anything is confidently synthetic, so CI or an upload hook can gate on it\n    if any(r[\"verdict\"] == \"synthetic\" and r[\"score\"] >= 0.90 for r in results):\n        sys.exit(1)\n\nif __name__ == \"__main__\":\n    main()\n```\n\nThe pipelines are cached in `_pipes`\n\nso each model loads once per process — model load dominates runtime, so in production you'd keep this warm behind a small HTTP service rather than spawning a process per file. The 0.90 gate threshold is a starting point; tune it against your own false-positive tolerance.\n\n## 4. Feed it real inputs\n\nCollect one known-real and one known-synthetic sample per modality: a photo off your phone plus an image from any diffusion model; a voice memo plus a clip from a TTS service; a paragraph you wrote plus one straight out of a chatbot pasted into `llm.txt`\n\n.\n\n```\npython detect.py phone-photo.jpg diffusion-render.png voicememo.wav llm.txt\n```\n\nFirst run downloads all three checkpoints from the Hugging Face Hub (~1.2 GB) into `~/.cache/huggingface`\n\n; later runs load from cache and classify each file in a few hundred milliseconds to a few seconds on CPU.\n\n## Verify it works\n\nYou should see one JSON object per file, with the synthetic samples flagged:\n\n```\n[\n  {\n    \"file\": \"phone-photo.jpg\",\n    \"modality\": \"image\",\n    \"verdict\": \"authentic\",\n    \"label\": \"human\",\n    \"score\": 0.9971,\n    \"model\": \"Organika/sdxl-detector\"\n  },\n  {\n    \"file\": \"diffusion-render.png\",\n    \"modality\": \"image\",\n    \"verdict\": \"synthetic\",\n    \"label\": \"artificial\",\n    \"score\": 0.9998,\n    \"model\": \"Organika/sdxl-detector\"\n  },\n  {\n    \"file\": \"voicememo.wav\",\n    \"modality\": \"audio\",\n    \"verdict\": \"authentic\",\n    \"label\": \"real\",\n    \"score\": 0.9842,\n    \"model\": \"MelodyMachine/Deepfake-audio-detection-V2\"\n  },\n  {\n    \"file\": \"llm.txt\",\n    \"modality\": \"text\",\n    \"verdict\": \"synthetic\",\n    \"label\": \"AI\",\n    \"score\": 0.9564,\n    \"model\": \"fakespot-ai/roberta-base-ai-text-detection-v1\"\n  }\n]\n```\n\nYour exact scores will differ. Then confirm the gate fired:\n\n```\necho $?   # → 1, because at least one file scored ≥0.90 synthetic\n```\n\nRun it again with only the real samples and `echo $?`\n\nshould print `0`\n\n.\n\n## Troubleshooting\n\n** ValueError: ffmpeg was not found but is required to load audio files from filename** — the audio pipeline decodes files by invoking FFmpeg. Install it (\n\n`brew install ffmpeg`\n\n/ `apt-get install -y ffmpeg`\n\n) and make sure it's on the PATH of the process running the script, which is easy to miss inside slim Docker images and systemd units.** Token indices sequence length is longer than the specified maximum sequence length for this model (743 > 512) followed by IndexError: index out of range in self** — you dropped\n\n`truncation=True`\n\nfrom the text call. Restore it; and remember truncation means only the first 512 tokens are scored, so chunk long documents and score each chunk if you care about the tail.** OSError: We couldn't connect to 'https://huggingface.co' to load this file** — first run needs Hub access. If your servers are egress-restricted, pre-download on a machine that isn't (\n\n`hf download Organika/sdxl-detector`\n\n, once per model — the `hf`\n\nCLI ships with `huggingface_hub`\n\n), copy `~/.cache/huggingface`\n\nacross, and set `HF_HUB_OFFLINE=1`\n\nin production.**Everything scores authentic, even known fakes** — check the input actually reached the model intact. Screenshots of AI images, re-encoded thumbnails, and voice notes transcoded by a chat app strip the artifacts detectors key on. Test with the original file, and treat detector evasion via re-encoding as a known limitation, not a bug in your wiring.\n\n## Next steps\n\nSingle-model verdicts are the weakest form of this pipeline. To harden it: ensemble two or more detectors per modality and require agreement before flagging; add provenance checks with [C2PA Content Credentials](https://c2pa.org) so signed-authentic media can skip ML scoring entirely; and benchmark on public datasets (CIFAKE and GenImage for images, ASVspoof for audio) before trusting any threshold. When you outgrow the CLI, wrap `get_pipe`\n\n/`detect`\n\nin a FastAPI service with the pipelines loaded at startup, and log every score — your own traffic distribution is the fine-tuning dataset that will eventually beat any off-the-shelf checkpoint.\n\n## Sources & further reading\n\n-\n[Organika/sdxl-detector model card](https://huggingface.co/Organika/sdxl-detector)— huggingface.co -\n[MelodyMachine/Deepfake-audio-detection-V2 model card](https://huggingface.co/MelodyMachine/Deepfake-audio-detection-V2)— huggingface.co -\n[fakespot-ai/roberta-base-ai-text-detection-v1 model card](https://huggingface.co/fakespot-ai/roberta-base-ai-text-detection-v1)— huggingface.co -\n[Transformers Pipelines documentation](https://huggingface.co/docs/transformers/main_classes/pipelines)— huggingface.co -\n[Hugging Face hf CLI guide](https://huggingface.co/docs/huggingface_hub/guides/cli)— huggingface.co -\n[transformers on PyPI](https://pypi.org/project/transformers/)— pypi.org\n\n[Emeka Okafor](https://sourcefeed.dev/u/emeka_okafor)· Security Editor\n\nEmeka has spent over a decade tracking threat actors, vulnerability disclosures, and the evolving landscape of application security, bringing a sharp continent-spanning perspective to his reporting. He's known for translating dense CVE advisories into clear, actionable context that developers and security teams alike actually read.\n\n## Discussion 0\n\nNo comments yet\n\nBe the first to weigh in.", "url": "https://wpnews.pro/news/detect-ai-generated-images-audio-and-text-with-open-source-models", "canonical_source": "https://sourcefeed.dev/a/detect-ai-generated-images-audio-and-text-with-open-source-models", "published_at": "2026-08-12 11:40:46+00:00", "updated_at": "2026-08-12 11:44:31.036840+00:00", "lang": "en", "topics": ["artificial-intelligence", "machine-learning", "generative-ai", "ai-tools", "ai-ethics"], "entities": ["Emeka Okafor", "Hugging Face", "Organika/sdxl-detector", "MelodyMachine/Deepfake-audio-detection-V2", "fakespot-ai/roberta-base-ai-text-detection-v1", "Mozilla", "Fakespot", "Transformers"], "alternates": {"html": "https://wpnews.pro/news/detect-ai-generated-images-audio-and-text-with-open-source-models", "markdown": "https://wpnews.pro/news/detect-ai-generated-images-audio-and-text-with-open-source-models.md", "text": "https://wpnews.pro/news/detect-ai-generated-images-audio-and-text-with-open-source-models.txt", "jsonld": "https://wpnews.pro/news/detect-ai-generated-images-audio-and-text-with-open-source-models.jsonld"}}