1 điểm bởi GN⁺ 2025-05-24 | 1 bình luận | Chia sẻ qua WhatsApp
  • Xuất phát từ vấn đề rằng ngay cả trong năm 2025, việc nghe và đồng bộ tự do các tệp nhạc người dùng sở hữu trên iPhone vẫn còn khó khăn, tác giả đã tự triển khai một trình phát nhạc ưu tiên cục bộ bằng SwiftUI
  • Nếu hủy đăng ký Apple Music, quá trình đồng bộ iCloud Music Library sẽ dừng; iTunes Match là một lựa chọn trả phí riêng, lưu bản sao AAC 256kbps trực tuyến với giá 24,99 USD/năm
  • React Native/Expo thường thất bại hoặc crash khi duyệt các thư mục iCloud lồng sâu và xử lý quyền tệp, nên triển khai SwiftUI dùng API native của Apple trở thành lựa chọn đơn giản hơn
  • Ứng dụng dùng SQLite FTS5 để tìm kiếm tên tệp và metadata như artist, album, title, đồng thời tách riêng các màn hình nhập từ iCloud, quản lý thư viện và phát nhạc
  • Do bookmark theo phạm vi bảo mật và giới hạn bản build phát triển cá nhân trên iOS, ngay cả trong quá trình dùng lâu dài một ứng dụng do cá nhân tự tạo, vẫn còn rào cản về truy cập tệp và phân phối

Vì sao tôi tự làm trình phát nhạc

  • Để phát các tệp nhạc người dùng sở hữu trên iPhone, vẫn còn tình trạng phải trả tiền cho Apple hoặc phải lách qua nhiều hạn chế
  • Với người dùng đã sắp xếp sẵn thư viện nhạc cục bộ, dịch vụ streaming gần với một tính năng tiện lợi hơn là thứ bắt buộc
  • Nếu hủy đăng ký Apple Music, việc đồng bộ giữa các thiết bị dựa trên iCloud Music Library sẽ bị dừng
    • Tính năng này nằm sau gói đăng ký
    • Có thể dùng lại bằng iTunes Match với giá 24,99 USD/năm
    • Match lưu bản sao AAC 256kbps trực tuyến, còn tệp gốc vẫn giữ nguyên trừ khi người dùng thay đổi
    • Nếu không có đăng ký, đồng bộ đám mây biến mất và phải quay lại đồng bộ qua cáp/Wi‑Fi
  • Mục tiêu là tự làm một trình phát nhạc cơ bản có thể nhập, sắp xếp và phát các tệp âm thanh
  • Ứng dụng hoàn thiện cung cấp tìm kiếm toàn văn, hỗ trợ iCloud, trải nghiệm ưu tiên cục bộ và được công khai trên GitHub

Vì sao các lựa chọn hiện có không phù hợp

  • Ứng dụng mặc định của Apple

    • Có thể phát trực tiếp tệp nhạc trên iCloud bằng ứng dụng Files, nhưng ứng dụng này không được thiết kế để nghe nhạc
    • Thiếu các tính năng cốt lõi như quản lý playlist, sắp xếp metadata và hàng đợi phát
    • Dù bản thân việc phát nhạc là khả thi, trải nghiệm người dùng tổng thể vẫn bị hạn chế; cũng đã có các thảo luận liên quan trong cộng đồng Apple
  • Ứng dụng bên thứ ba

    • Trên App Store có nhiều ứng dụng phát nhạc offline, nhưng nhiều ứng dụng áp dụng giá theo đăng ký ngay cả với việc phát các tệp mà người dùng đã sở hữu
    • Doppler có ưu điểm là mô hình thanh toán một lần
    • Tuy nhiên UX tập trung vào quản lý album, chất lượng tìm kiếm không thỏa mãn, và việc nhập từ iCloud với nhiều thư mục lồng nhau chậm và khó dùng

Quá trình chuyển từ React Native sang SwiftUI

  • Lựa chọn ban đầu: React Native/Expo

    • Vì trải nghiệm trước đây với Swift, tác giả muốn tránh Swift và trước tiên chọn React Native/Expo để tái sử dụng kinh nghiệm phát triển web
    • Việc triển khai UI phát nhạc khá dễ, và tác giả dùng template music-player của Gionatha Sturba, vốn trông có vẻ có đủ tính năng cần thiết
    • Vấn đề lớn lên ở phần truy cập hệ thống tệp và đồng bộ tệp đám mây
    • Các thư viện như expo-filesystem hỗ trợ chọn tệp cơ bản, nhưng việc duyệt đệ quy các thư mục iCloud lồng sâu thường thất bại hoặc làm ứng dụng crash
    • Sandbox của iOS ngăn ứng dụng đọc tệp nếu không có quyền rõ ràng từ người dùng
    • Kết quả là cách tiếp cận dựa trên JavaScript trở nên phức tạp hơn so với dùng trực tiếp API native của Apple; chuyển sang Swift cho phép kiểm soát tốt hơn truy cập tệp iCloud và quyền sandbox
  • Vì sao chọn SwiftUI

    • Thay vì UIKit hoặc storyboard, tác giả chọn SwiftUI để tạo tầng UI khai báo và tập trung vào logic miền cùng đồng bộ dữ liệu
    • Sự tích hợp async/awaitSwift Actors của Swift giúp việc quản lý luồng dữ liệu và concurrency dễ hơn
    • SwiftUI giúp cấu trúc ứng dụng thành các thành phần ViewModel độc lập
    • Các LLM như OpenAI o1 và DeepSeek tạo ít phụ thuộc chéo phức tạp hơn khi sinh mã UI thuần hoặc mã data binding

Cấu trúc ứng dụng và mô hình dữ liệu

  • Ba màn hình chính

    • Ứng dụng được chia thành ba luồng: Library import, Library management, Player and playback
    • Library import thêm thư mục thư viện iCloud, quét tệp âm thanh trong mọi thư mục và chèn đường dẫn vào cơ sở dữ liệu SQLite
    • Library management quản lý các bài hát đã thêm và tổ chức playlist
    • Player and playback phụ trách lặp lại, shuffle, quản lý hàng đợi, phát/dừng/bài tiếp theo
    • Bộ chọn tệp mặc định của Apple không phù hợp với luồng chọn cùng lúc nhiều thư mục và nhiều tệp đã tìm bằng từ khóa
    • Khi chạy ứng dụng với thư viện trống, tab Sync hiển thị nút “Add iCloud Source”
    • Khi chọn thư mục, ứng dụng hiển thị thanh tiến trình trong lúc duyệt cây thư mục, và khi lập chỉ mục xong thì chuyển sang tab Library
    • Màn hình đầu tiên hiển thị Playlists / Artists / Albums / Songs
    • Khi nhấn vào một track, Mini-Player xuất hiện ở phía dưới; nhấn vào đó sẽ chuyển sang Player toàn màn hình
    • Player toàn màn hình cung cấp shuffle, lặp lại, sắp xếp lại hàng đợi và âm lượng
    • Trong Sync, nhấn “+” để chọn thư mục khác sẽ hợp nhất bài hát mới ở nền mà không cần khởi động lại
  • Tầng logic kiểu server

    • Dù là ứng dụng di động, tác giả áp dụng kiến trúc kiểu backend dựa trên kinh nghiệm với backend web/đám mây
    • Tách tầng miền/logic khỏi tầng View và ViewModel để xử lý ổn định đồng bộ đám mây, phân tích metadata và truy cập dữ liệu SQLite
    • Cấu trúc tầng như sau
      • SQLite lưu các hàng bài hát gốc và chỉ mục FTS
      • Repository bọc cơ sở dữ liệu và cung cấp API bất đồng bộ
      • Domain Actor sở hữu các quy tắc nghiệp vụ như nhập dữ liệu, tìm kiếm và logic hàng đợi
      • ViewModel đăng ký theo dõi Actor và chuyển đổi thành struct dùng cho UI
      • SwiftUI View render dữ liệu được truyền vào
    • Các thay đổi trạng thái được giữ thread-safe, còn đồng bộ iCloud, phát nhạc và UI được tách riêng để không nhảy tầng trực tiếp

Tìm kiếm cục bộ bằng SQLite FTS5

  • Bộ lưu trữ bền vững dùng SQLite, không dùng CoreData
  • Lý do tránh CoreData là cần kiểm soát trực tiếp schema, truy vấn thô và đặc biệt là tìm kiếm toàn văn
  • Từ khoảng iOS 11 trở đi, có thể dùng SQLite kèm tính năng FTS mà không cần cấu hình thêm
  • Tác giả dùng SQLite.swift cho các truy vấn thông thường, nhưng xử lý truy vấn FTS bằng câu lệnh SQL thường
  • SQLite FTS5 cho phép truy vấn tên tệp và metadata như artist, album, title mà không cần hạ tầng tìm kiếm riêng
  • Cấu hình bảng FTS

    • Có hai bảng FTS5 được dùng
    • songs_fts: được SQLiteSongRepository sử dụng, lập chỉ mục artist, title, album, albumArtist
    • source_paths_fts: được SQLiteSourcePathSearchRepository sử dụng, lập chỉ mục fullPath, fileName
    • Hai bảng FTS nằm cạnh các bảng B-tree cơ bản là songs, source_paths
    • FTS là chỉ đọc từ UI, mọi thao tác ghi được xử lý bên trong Repository
    • Ví dụ tạo songs_fts đặt songIdUNINDEXED và dùng tokenizer unicode61
    • Tác giả chọn unicode61 để xử lý nhiều loại ký tự
    • Các khóa không dùng để tìm kiếm được đánh dấu UNINDEXED để từ điển thuật ngữ không phình to không cần thiết
  • Tìm kiếm một phần và xếp hạng

    • Khi người dùng nhập “lumine”, bên trong ứng dụng gắn wildcard như “lumine*” để lập tức tìm kết quả tìm kiếm một phần
    • Việc sắp xếp kết quả tìm kiếm dùng bm25 của SQLite
    • Cách này cung cấp schema có thể dự đoán, cách tiếp cận ưu tiên cục bộ, tìm kiếm toàn văn mạnh mẽ, mà không thêm phụ thuộc mạng hay dịch vụ bên ngoài

Truy cập tệp trên iOS và hạn chế bookmark

  • Ứng dụng iOS có thể lưu bookmark lâu dài để ghi nhớ vị trí tệp
  • Tuy nhiên security-scoped bookmarks, thứ cấp quyền truy cập mở rộng vào tệp bên ngoài sandbox ứng dụng, chỉ được cung cấp trên macOS
  • Ứng dụng iOS có thể dùng bookmark thông thường để ghi nhớ đường dẫn tệp và yêu cầu truy cập lại qua document picker, nhưng không có gì đảm bảo quyền truy cập đó sẽ âm thầm tiếp tục được duy trì
  • Nội dung liên quan có trong tài liệu bookmark của Apple
  • Để giảm nhẹ vấn đề này, tác giả triển khai cơ chế thay thế: sao chép tệp vào container sandbox của chính ứng dụng
    • Khi bookmark còn hiệu lực, ứng dụng chủ động sao chép tệp ở nền
    • Ngay cả khi iOS đặt lại quyền, điều này giúp giảm rủi ro truy cập đến tham chiếu tệp âm thanh không hợp lệ
  • Cách tiếp cận này cũng cải thiện tốc độ lập chỉ mục
    • Quét cấu trúc thư mục một lần trong khi quyền truy cập còn hoạt động
    • Chỉ nhập các tệp âm thanh liên quan
    • Duyệt an toàn các thư mục lồng sâu
  • Vấn đề phát ổn định từng tệp âm thanh ở vị trí bên ngoài sau khi thiết bị khởi động lại vẫn chưa được giải quyết
  • Ngay cả với ứng dụng native, ca sử dụng này vẫn chưa được iOS hỗ trợ đầy đủ, và xử lý truy cập tệp một cách ổn định vẫn còn phức tạp

Triển khai phát nhạc và UI

  • Phân tích metadata

    • Việc phân tích metadata của tệp âm thanh dùng AVURLAsset trong framework AVFoundation của Apple
    • AVURLAsset có thể kiểm tra metadata tệp media như title, album artist
    • Một số trường như track number phải được tìm trực tiếp trong tag ID3
    • Vì tài liệu chính thức không bao quát đủ các edge case, tác giả tham khảo các ví dụ triển khai qua tìm kiếm GitHub
  • Phát âm thanh

    • Sau khi lập chỉ mục thư viện, trình phát âm thanh được triển khai bằng cách khởi tạo và phát các instance AVAudioPlayer
    • Để điều khiển nhạc từ Control Center, cần triển khai protocol AVAudioPlayerDelegate và kết nối với MPRemoteCommandCenter của Apple
    • MPRemoteCommandCenter cho phép ứng dụng phản hồi điều khiển phát nhạc ở cấp hệ thống

Trải nghiệm phát triển với Swift và Apple

  • Những điểm khó

    • Preview SwiftUI thời gian thực của Xcode là một bước tiến, nhưng trải nghiệm phát triển tổng thể vẫn chưa đạt mức tích hợp VSCode, reload simulator thời gian thực và công cụ debug quen thuộc mà Flutter đã cung cấp từ 5 năm trước
    • Hỗ trợ LSP cho Swift trên Neovim hoặc VSCode cần công cụ bổ sung như xcode-build-server, và không giống trải nghiệm phát triển của hệ sinh thái thiên về web
    • Một phần Apple SDK vẫn còn mang phong cách Objective-C
    • Tìm kiếm tệp Spotlight chỉ được expose qua NSMetadataQuery, và NSMetadataQuery dùng KVO cùng key dạng chuỗi
    • Chưa có wrapper thân thiện với Swift
    • UI khai báo của SwiftUI hữu ích, nhưng hành vi toàn ứng dụng có liên quan đến quyền iCloud không thể được giả lập trong preview, nên phải tự mock các tương tác đám mây
  • Những điểm tốt

    • Nhờ async/await, có thể viết mã concurrency thiên về I/O như mã mệnh lệnh mà không cần callback
    • Có thể dễ dàng đưa cả mã đồng bộ vào Actor và gọi như trong hệ sinh thái JavaScript
    • Có thể dùng trực tiếp thư viện native của Apple, không bị giới hạn bởi các binding mã nguồn mở của React Native hay Flutter
    • Nhiều API của Apple có ví dụ nên dễ bắt đầu
    • Cách cấu trúc UI kiểu React của SwiftUI đem lại năng suất và không gian khám phá

iOS khiến việc dùng lâu dài ứng dụng cá nhân trở nên khó khăn

  • Sau khoảng 1,5 tuần triển khai, tác giả đã tạo được một trình phát nhạc cục bộ/offline có thể nhập tệp âm thanh từ kho iCloud
  • Nhưng nếu không có chứng chỉ nhà phát triển, ứng dụng chỉ chạy được 7 ngày, sau đó phải build lại
  • Cần trả 99 USD để đăng ký Apple Developer Program
  • Ngay cả sau DMA Act của EU, sideloading vẫn chưa hoàn toàn mở
    • Người dùng EU có thể cài ứng dụng marketplace bên thứ ba từ website nhà phát triển
    • Nhà phát triển vẫn phải đăng ký chương trình 99 USD/năm của Apple
    • Cũng phải đồng ý với Alternative Terms của Apple
    • Với mục đích cá nhân/sở thích, giới hạn 7 ngày của bản build phát triển không biến mất
  • PWA trên iOS cũng vẫn còn hạn chế
    • Ngay cả sau các bản cập nhật iOS 16~18.x, PWA vẫn chạy trong sandbox của Safari
    • Có thể dùng WebGL2 và web-push
    • Không cung cấp Web Bluetooth, USB, NFC, Background Sync, hay bộ nhớ bảo đảm vượt khoảng 50MB
    • WebGL đi qua Metal shim, nên framerate thực tế thường thua ứng dụng Metal native
  • AI giúp cung cấp dễ dàng hơn kiến thức cần thiết để xử lý các công nghệ chưa quen, qua đó giảm độ phức tạp của phát triển phần mềm, nhưng ứng dụng iOS vẫn phải tuân theo các quy tắc mang tính nhân tạo
  • Ngay cả với ứng dụng do cá nhân tự làm, để chạy quá một tuần vẫn còn chướng ngại cuối cùng từ Apple, và điều này hạn chế phát triển cũng như phân phối ứng dụng cá nhân

1 bình luận

 
GN⁺ 2025-05-24
Các ý kiến trên Hacker News
  • Tôi đã trải qua thời kỳ Winamp là trình phát nhạc mặc định, và ngay cả trong thời đại streaming, tôi vẫn sắp xếp thư viện nhạc cục bộ của mình theo thư mục
    Giống như những người khác trong phần bình luận này, tôi đã làm một trình phát nhạc kiểu cũ như một dự án sở thích để nghe nhạc offline; đó là một ứng dụng HTML/JS một trang, có đầy đủ thao tác bằng bàn phím và chức năng hàng đợi đơn giản
    Có thể xem thử tại: https://nobsutils.com/mp

    • Đến giờ, sau khoảng 27 năm, tôi vẫn nghĩ UI của Winamp gần như là đáp án đúng
      Tôi thích sự đơn giản như tập hợp file trong một thư mục, shuffle toàn bộ bộ sưu tập, hoặc chỉ phát một thư mục cụ thể
    • Tôi thích cái này vì đang tìm một trình phát nhạc đơn giản như vậy
      Nhân tiện, phím tắt bookmark tiêu chuẩn hiện nay là cmd + d lại đổi theme thay vì đánh dấu trang web
    • Với tôi, trình phát nhạc mặc định luôn là foobar2000, và giờ tôi dùng ứng dụng Cog để thay thế
  • Tôi đã xây dựng bộ sưu tập nhạc trong định dạng FLAC suốt 25 năm, và năm ngoái mua một điện thoại Android cùng thẻ MicroSD 1TB để có thể cho toàn bộ nhạc vào đó
    Đó là một dự án dài chờ công nghệ bắt kịp, nhưng giờ có thể bỏ tất cả vào túi nên tôi khá hài lòng
    Chắc chắn không chỉ mình tôi không muốn trở thành người đi thuê, phải streaming thứ ngành công nghiệp thúc ép, chịu quảng cáo và từ bỏ quyền kiểm soát; và cũng thật tuyệt khi thấy những người còn tự làm cả ứng dụng của mình

    • Công nghệ đã bắt kịp từ lâu rồi; trường hợp này gần với việc cố chấp dùng một định dạng không phù hợp mục đích hơn
      Nếu tái mã hóa tốt, bạn có thể đưa toàn bộ nhạc vào một thẻ nhỏ hơn nhiều với chất lượng âm thanh trong suốt đến mức không nghe ra khác biệt, còn FLAC thì giữ trên desktop làm bản sao lưu
    • Bạn tuyển chọn bộ sưu tập thật sự rất tốt
      Bộ sưu tập của tôi chỉ có khoảng 25% là FLAC/APE/ALAC/WavePack mà đã hơn 3TB, nên rất khó nghe nhạc khi di chuyển
      Tôi không thể chọn trước sẽ cho gì vào thiết bị di động
    • Tôi cũng đang xây dựng bộ sưu tập cá nhân chỉ dùng FLAC, dù thời gian ngắn hơn 25 năm nhiều, và đã vượt 1TB
      Kết hợp server https://www.navidrome.org với client https://symfonium.app dùng rất tốt
      Giờ đã có thẻ SD 2TB, nên nếu giá giảm có lẽ tôi sẽ mua một cái
    • Trên Android, vấn đề ảnh bìa và tiêu đề không ổn định luôn tồn tại
      Dù thay đổi cũng không áp dụng, hoặc đã áp dụng rồi bỗng đổi sang ảnh bìa sai hoàn toàn; nhìn thì giống lỗi Android
      Tôi tò mò không biết bạn có gặp vấn đề này không
  • Tôi tự làm một web app để có thể nghe trọn album nhưng vẫn tạm dừng giữa chừng hoặc đổi thiết bị
    Tôi thích nghe album từ đầu đến cuối, nhưng ít nhất YouTube Music không nhớ vị trí phát, và khi mở lại album trên thiết bị khác thì phải tự tìm điểm đã dừng, rất bất tiện
    Web app của tôi cho phép dán URL, server sẽ tải xuống bằng yt-dlp rồi có thể stream từ đó; nó luôn nhớ vị trí phát, nên tôi có thể nghe bằng điện thoại trong xe rồi đến chỗ làm tiếp tục nghe trên laptop
    Nó cũng rất hợp khi thêm các mix từ nguồn khác như NTS Radio

    • Điều khiến tôi khó chịu nhất ở YouTube Music chính là hàng đợi có thể lưu được và việc chuyển thiết bị mượt hơn
      Nếu web app đó được công khai, tôi muốn xem thử
  • Tôi chưa đọc hết nhưng đây là một bài viết hay, và tôi thích đọc về việc lập trình viên đã đưa ra các quyết định chi tiết hơn như thế nào và vì sao
    Tôi đồng cảm với ý nghĩ rằng những trình phát audio đã thử đều không vừa ý
    Trong thế giới ứng dụng nhạc, bố cục màn hình và UI dường như gần như đã trở thành phổ quát, nhưng tôi không thích điều đó và cũng không thật sự hiểu
    Cảm giác như đang đánh nhau với mọi ứng dụng nhạc, nên tôi rất hoan nghênh những ai muốn thử làm một thứ gì đó mới

  • Tôi vẫn dùng ứng dụng Apple Music bằng cách cho file cục bộ của mình vào đó
    Tôi tắt dịch vụ streaming Apple Music, import tất cả vào ứng dụng Apple Music trên macOS, rồi cắm điện thoại vào laptop như năm 2007 để đồng bộ như iPod
    Mọi thứ hoạt động đúng như kỳ vọng, và nhạc của tôi không thay đổi thường xuyên nên việc đồng bộ cũng không thành vấn đề
    Đồng bộ bằng dây còn đem lại một cảm giác hoài niệm kỳ lạ

    • Theo tôi biết thì đồng bộ Wi‑Fi tự động bằng iTunes vẫn hoạt động tốt
  • Tôi khó đồng ý với nhận định rằng trước khi có async/await, viết code concurrency trong Swift cảm giác thô hơn và nhiều boilerplate hơn so với Go hay JS/TS
    Xử lý bất đồng bộ có thể khiến việc viết code concurrency dễ hơn, nhưng khi codebase lớn lên, việc suy luận có thể trở nên kém đơn giản hơn
    Trong một codebase bất đồng bộ phức tạp, việc hiểu luồng code và concurrency khó hơn
    Nếu mục tiêu là giảm chi phí thực thi code bằng thread thì có giải pháp là green thread nhẹ, còn nếu mục tiêu là giảm chi phí bảo trì code dùng thread thì về lâu dài bất đồng bộ có khả năng đòi hỏi nhiều công sức hơn

    • Concurrency tốt phải khiến việc hiểu và suy luận trở nên đơn giản hơn khi code lớn lên
      Chỉ riêng đóng gói dựa trên process hoặc service cũng đã mang lại lợi ích lớn
      Tôi xem đây không phải là thất bại của bản thân concurrency, mà gần hơn với giới hạn của trừu tượng async/await
    • Trong trường hợp này, mục tiêu là một trình phát audio đơn giản, nên có lẽ sẽ không thành vấn đề lớn
  • Tôi đã kỳ vọng bài viết sẽ nói không chỉ về phần mềm quản lý và phát nhạc, mà còn về thiết bị vật lý
    Vài năm trước, tôi định mua một máy nghe nhạc MP3 cho cậu con trai 10 tuổi rất thích nghe nhạc nhưng chưa sẵn sàng dùng điện thoại, và tôi đã ngạc nhiên vì các lựa chọn quá tệ
    Tôi nghĩ việc Apple ngừng sản xuất iPod đã tạo ra một khoảng trống lớn mà không ai lấp được
    Chiếc iPod shuffle dạng USB stick là máy nghe nhạc MP3 tốt nhất tôi từng dùng: nhỏ, cắm trực tiếp không cần cáp riêng, pin cũng rất lâu
    Nó không có màn hình để duyệt nhạc, nhưng đó là chủ ý; cứ để shuffle lo là được
    Thật đáng tiếc là ngay cả một ý tưởng tương đối đơn giản như vậy cũng không được sao chép tử tế trên thị trường phần cứng
    Mọi người có thể nói vấn đề không phải phần cứng mà là phần mềm/DRM, nhưng việc không có thiết bị phát nhạc di động giá rẻ tốt thật sự rất đáng tiếc

    • Tôi nghĩ thay đổi thực sự ở đây không phải là sự biến mất của iPod
      Chính sự tồn tại của Spotify và smartphone đã giết chết máy nghe nhạc MP3, và cả hai chiếm quá nhiều “không khí” của thị trường đến mức làm phần còn lại ngạt thở
    • Fiio đang làm khá nhiều sản phẩm trong phân khúc này
      Ví dụ có https://www.fiio.com/cp13https://www.fiio.com/jm21
    • Có rất nhiều iPod cũ, và khá nhiều mẫu dùng ổ cứng đời cũ cũng tương đối dễ mod sang bộ nhớ flash, nên đó có thể là một lựa chọn
      Nó cũng là một dự án giáo dục nhỏ khá ổn để học điện tử và tái sử dụng thiết bị “cũ”
      Có nhiều lựa chọn tùy biến ngoại hình, và cũng có thể mod sâu hơn như thêm Bluetooth hay USB‑C
      Như những người khác đã nói, phía phần mềm vẫn hoạt động tốt với iTunes trên Windows và tích hợp Finder/Music trên macOS
    • Tôi nghĩ vấn đề gần với nhu cầu hơn là vấn đề phần cứng hay phần mềm
      Các nhà sản xuất Trung Quốc đang bán những thiết bị trông đẹp, phát nhạc được và có cả chức năng smartphone với giá 50–100 đô la, kiểu Mini iPhone 16 hay Mini S24
      Phụ huynh nhiều khả năng sẽ mua các thiết bị tương tự cho con thay vì máy nghe nhạc MP3
      Không đưa điện thoại cho con trai 14 tuổi là một cách nuôi dạy không theo thông lệ và tôi tôn trọng điều đó, nhưng có vẻ nhu cầu như vậy không lớn hơn mức nguồn cung hiện có
    • Sony vẫn làm những máy nghe nhạc khá tốt dưới thương hiệu Walkman: https://electronics.sony.com/audio/walkman-digital-recorders...
      Có thể hơi đắt với một đứa trẻ 10 tuổi, nhưng biết đâu tìm được hàng cũ trên eBay
  • Với tôi, tổ hợp quản lý nhạc cục bộ bằng Music.app và đồng bộ iPhone bằng Finder vẫn còn dùng tốt
    Tuy vậy, Music.app dường như đã không được bảo trì suốt nhiều năm sau bản viết lại tệ hại thời Big Sur, và cũng có các lỗi khó chịu
    Bất chấp các nhược điểm, tổ hợp này là giải pháp quản lý thư viện nhạc + đồng bộ di động tốt nhất tôi từng thấy, nhưng vì phần mềm không được bảo trì và cũng không đa nền tảng, cuối cùng có lẽ tôi sẽ phải tự viết hệ thống

    • Một phần vấn đề của bản “viết lại” Music nằm ở chỗ nó giống sao chép-dán từ iTunes hơn là thực sự viết lại
      Vẫn còn rất nhiều sự kỳ quặc đặc trưng của iTunes, như cửa sổ thiết lập/tùy chọn modal là tàn tích từ thời OS 9
      Cửa sổ thiết lập trên OS X không nên là modal
      Tôi đoán bên trong họ đang làm một phiên bản được xây lại từ đầu, giống như Music cho Windows dựa trên WinUI hoàn toàn mới
    • Trên chiếc iPod Video thế hệ 5 của tôi, đồng bộ Finder tích hợp sẵn vẫn còn hỏng khá nhiều
      Khó chịu nhất là đồng bộ podcast; thời iTunes phụ trách thì ổn, nhưng trong đồng bộ Finder của Big Sur có lỗi khiến nó không nhớ vị trí phát nếu chuyển sang track hoặc podcast khác rồi quay lại
      Vì vậy, podcast dài hơn vài phút gần như không dùng được trên thiết bị
    • Cũng có thể thử ứng dụng của tôi: https://www.plastaq.com/minimoon
  • Người ta thật sự tự làm ứng dụng nghe nhạc thay vì chuyển sang Android
    Không biết là vì bong bóng chat màu xanh, hay vì mọi thứ “cứ thế là chạy”, ngoại trừ phát nhạc offline

    • Bạn thật sự sẽ chuyển sang một nước khác chỉ vì bánh mì ở đó ngon hơn sao?
      Tôi không thấy tự nướng thì có vấn đề gì
    • Tôi đã làm một prototype trình phát nhạc cho iOS
      Lý do là ứng dụng VLC không phân tích metadata của FLAC trên file server của tôi một cách ổn định, và vì giới hạn dung lượng lưu trữ nên tôi cũng không thể lưu toàn bộ bộ sưu tập nhạc lên thiết bị
      Ứng dụng của tôi vẫn là prototype ở chỗ tôi muốn có thêm nhiều tính năng, nhưng nó đã có phát âm thanh, truy cập file từ xa và phân tích metadata FLAC, nên hoạt động đủ tốt để tôi thiếu động lực triển khai thêm tính năng
      Giống tác giả, ban đầu tôi muốn dùng React Native vì đã có kinh nghiệm và cũng đang bảo trì vài ứng dụng, nhưng tôi không muốn nhắm tới hoặc debug cho nền tảng khác
      Vì vậy tôi quyết định thử SwiftUI và dùng một công cụ đặc biệt[1] để tạo ra thứ gần giống hot reload
      Đây là một hack khá bẩn, cần thêm cờ linker tùy chỉnh vào Xcode, nhưng nó hoạt động đủ để tôi không còn nhớ trải nghiệm developer của TypeScript và React Native
      [1] https://github.com/johnno1962/InjectionIII
    • Người ta thật sự viết code để tránh Android
    • foobar2000 đã có trên App Store từ lâu rồi
      Thật ra tôi thấy hơi lạ khi tác giả không tìm được ứng dụng nghe nhạc miễn phí nào ưng ý
      Dù vậy, không nhất thiết phải có cớ để làm một thứ gì đó, nên có thể đó chỉ là câu chuyện để mở đầu
    • Tôi đang dùng tổ hợp ứng dụng navidrome/substreamer trên iOS và nó hoạt động tốt
      Cũng có thể giữ những bài nhạc đã chọn trên thiết bị
  • Nếu bạn có bộ sưu tập nhạc offline thì tôi thực sự khuyên dùng https://play.google.com/store/apps/details?id=in.krosbits.mu...
    Hoạt động rất tốt, không gặp vấn đề gì

    • Symfonium cũng rất tuyệt
      Cũng hỗ trợ Plex, Jellyfin, WebDAV, SMB, v.v.