Skip to main content

flet-media-scanner

A Flet extension for Android MediaStore integration — save, list, and delete media files in the device Gallery / Music / Pictures without requiring broad storage permissions.

Supports video, audio, and image files. MIME type is resolved automatically from the file extension.

Requirements

  • Platform: Android only (no-op on other platforms)
  • Android: API 23+ (minSdk 23)
  • Flet: >= 0.86.0

Supported Formats

🎬 Video

Extension MIME Type Destination
.mp4 video/mp4 Movies/<album>/
.mkv video/x-matroska Movies/<album>/
.webm video/webm Movies/<album>/
.avi video/x-msvideo Movies/<album>/
.mov video/quicktime Movies/<album>/
.3gp video/3gpp Movies/<album>/
.ts video/mp2t Movies/<album>/
.flv video/x-flv Movies/<album>/

🎵 Audio

Extension MIME Type Destination
.mp3 audio/mpeg Music/<album>/
.m4a audio/mp4 Music/<album>/
.aac audio/aac Music/<album>/
.flac audio/flac Music/<album>/
.opus audio/opus Music/<album>/
.wav audio/wav Music/<album>/
.ogg audio/ogg Music/<album>/
.wma audio/x-ms-wma Music/<album>/

🖼 Image

Extension MIME Type Destination
.jpg / .jpeg image/jpeg Pictures/<album>/
.png image/png Pictures/<album>/
.gif image/gif Pictures/<album>/
.webp image/webp Pictures/<album>/
.bmp image/bmp Pictures/<album>/
.heic image/heic Pictures/<album>/
.heif image/heif Pictures/<album>/
.avif image/avif Pictures/<album>/
.tiff image/tiff Pictures/<album>/

Installation

pip install flet-media-scanner

Setup

Register the extension in your pyproject.toml:

[tool.flet.extensions]
flet_media_scanner = "flet_media_scanner.Extension"

Usage

import os
import flet as ft
from flet_media_scanner import MediaScanner, SaveResult

async def main(page: ft.Page):
    scanner = MediaScanner()
    storage = ft.StoragePaths()
    page.services.extend([scanner, storage])
    page.update()

    # Use StoragePaths to get the app cache directory (cross-device safe)
    cache_dir = await storage.get_application_cache_directory()

    # ── Video ──────────────────────────────────────────────────────────────
    video_path = os.path.join(cache_dir, "video.mp4")
    result: SaveResult = await scanner.save_video(
        video_path,
        file_name="my_video.mp4",
        album="MyApp",
    )
    if result.success:
        print(f"Video saved: {result.content_uri}")

    videos = await scanner.list_videos(album="MyApp")
    for v in videos:
        print(v["display_name"], v["content_uri"])

    # ── Audio ──────────────────────────────────────────────────────────────
    audio_path = os.path.join(cache_dir, "song.mp3")
    result = await scanner.save_audio(
        audio_path,
        file_name="song.mp3",
        album="MyApp",
    )
    if result.success:
        print(f"Audio saved: {result.content_uri}")

    tracks = await scanner.list_audio(album="MyApp")
    for t in tracks:
        print(t["display_name"], t["mime_type"])

    # ── Image ──────────────────────────────────────────────────────────────
    image_path = os.path.join(cache_dir, "photo.jpg")
    result = await scanner.save_image(
        image_path,
        file_name="photo.jpg",
        album="MyApp",
    )
    if result.success:
        print(f"Image saved: {result.content_uri}")

    images = await scanner.list_images(album="MyApp")
    for img in images:
        print(img["display_name"], img["size"])

    # ── Delete (works for any media type) ──────────────────────────────────
    deleted = await scanner.delete_media("content://media/external/video/media/123")
    print("Deleted:", deleted)

ft.run(main)

API

MediaScanner (Service)

Add to page.services before calling any methods.


Video

await save_video(file_path, file_name=None, album="MyApp") → SaveResult

Copies a private app video into Movies/<album> via Android MediaStore.

await list_videos(album="MyApp") → list[dict]

Returns all videos saved to the album.


Audio

await save_audio(file_path, file_name=None, album="MyApp") → SaveResult

Copies a private app audio file into Music/<album> via Android MediaStore.

await list_audio(album="MyApp") → list[dict]

Returns all audio files saved to the album.


Image

await save_image(file_path, file_name=None, album="MyApp") → SaveResult

Copies a private app image into Pictures/<album> via Android MediaStore.

await list_images(album="MyApp") → list[dict]

Returns all images saved to the album.


Delete

await delete_media(content_uri) → bool

Deletes any MediaStore item (video, audio, or image) by its content:// URI.

await delete_video(content_uri) → bool

Alias for delete_media(). Kept for backwards compatibility.


Common parameters for save_*

Parameter Type Description
file_path str Absolute path to the source file
file_name str | None Display name (defaults to the source file basename)
album str Subfolder inside Movies/, Music/, or Pictures/

SaveResult (dataclass)

Field Type Description
success bool Whether the operation succeeded
content_uri str MediaStore content:// URI
display_name str File name as shown in the gallery/app
mime_type str e.g. video/mp4, audio/mpeg, image/jpeg
relative_path str e.g. Movies/MyApp/
source_path str Original source file path
size int File size in bytes
error str Error message if success=False

List item fields (list_videos, list_audio, list_images)

Each dict contains: content_uri, display_name, mime_type, relative_path, size, date_added, date_modified.

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

flet_media_scanner-1.0.0.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

flet_media_scanner-1.0.0-py3-none-any.whl (13.6 kB view details)

Uploaded Python 3

File details

Details for the file flet_media_scanner-1.0.0.tar.gz.

File metadata

  • Download URL: flet_media_scanner-1.0.0.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for flet_media_scanner-1.0.0.tar.gz
Algorithm Hash digest
SHA256 887c35b8a338828065468fff83fdb2888bebdc9b56749da1fc06c29a0ceb7bed
MD5 2f1ebb18a5f16a1a0405deccd19a4af5
BLAKE2b-256 cca978a1afab77eda52e10c68b1a0578757215b2b1caf58b02a921371671081d

See more details on using hashes here.

File details

Details for the file flet_media_scanner-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for flet_media_scanner-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 e0cf260ea9d64cdf2d3f79d9ef403f0baa197b66ebc64c36e6658ad1e21d56b3
MD5 fc06e3a2f39afbe78665bdced4bfafbe
BLAKE2b-256 faf747d034b36abebca0448a94f342e4ff388b6b121c77761212f5f110f80205

See more details on using hashes here.

Release history Release notifications | RSS feed

1.7.0

2 files

1.6.0

2 files

1.5.0

2 files

1.4.0

2 files

1.3.0

2 files

1.2.0

2 files

1.1.0

2 files

1.0.1

2 files

This release

1.0.0 This release

2 files

0.86.5

2 files

0.86.4

2 files

0.86.3

2 files

0.86.2

2 files

0.86.1

2 files

0.86.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page