Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Files are being corrupted on iOS #237

Open
HelloItsMeAdm opened this issue Apr 30, 2023 · 1 comment
Open

[BUG] Files are being corrupted on iOS #237

HelloItsMeAdm opened this issue Apr 30, 2023 · 1 comment
Labels
bug Something isn't working

Comments

@HelloItsMeAdm
Copy link

HelloItsMeAdm commented Apr 30, 2023

Describe the bug
I started using my app on the iOS instead of android and i found that on android files play normally and work as they should. But on the iOS they seem to be somehow corrupted. They cant be played, even using app like VLC. It shows the duration of the files (sometimes) and the size seems to be ok. I tried both downloading mp3 and aac but non of these work.

To Reproduce
Include the code which doesn't work in the code markdown..

Future<void> download(
      String id, BuildContext context, String title, bool useSnacker) async {
    String basePath = await getAppSpecificFilesDir();

    final String mp3Path = "$basePath/mp3/$id.mp3";
    final String thumbnailPath = "$basePath/thumbnails/$id.jpg";

    await createFolders(basePath);

    await downloadThumbnail(thumbnailPath, id);

    // Check if file already exists or if path is invalid
    if (basePath == "" || await File(mp3Path).exists()) {
      return;
    }

    final manifest = await yt.videos.streamsClient.getManifest(id);
    final streamInfo = manifest.audioOnly.withHighestBitrate();

    var stream = yt.videos.streamsClient.get(streamInfo);

    // Open a file for writing.
    var file = File(mp3Path);
    var fileStream = file.openWrite();

    if (useSnacker) {
      Snacker().show(
        context: context,
        contentType: ContentType.warning,
        title: "Downloading started...",
        message: title,
      );
    }

    // Write the stream to the file.
    await stream.pipe(fileStream);

    // Close the file.
    await fileStream.flush();
    await fileStream.close();

    //wait for the thumbnail to be downloaded and then show the snackbar
    while (!await File(thumbnailPath).exists()) {
      await Future.delayed(const Duration(milliseconds: 100));
    }

    if (useSnacker) {
      Snacker().show(
        context: context,
        contentType: ContentType.success,
        title: "Download complete!",
        message: title,
      );
    }
    print("Download for $id complete!");
  }

Enviroment: (please complete the following information):

  • Enviroment: [Flutter o Dart VM]
  • Version 3.7.12
  • YoutubeExplode Version 1.12.3

EDIT
It seems that final streamInfo = manifest.audioOnly.withHighestBitrate(); was making problems, when i changed it to final streamInfo = manifest.muxed.withHighestBitrate(); it solved it.

@HelloItsMeAdm HelloItsMeAdm added the bug Something isn't working label Apr 30, 2023
@Aruljebaraj
Copy link

Aruljebaraj commented Jan 15, 2025

facing same issue any solution?

Future<void> indir(BuildContext context, String id, String adi) async {
  try {
    // Show a progress indicator while downloading
    showDialog(
      context: context,
      barrierDismissible: false,
      builder: (BuildContext context) {
        return AlertDialog(
          title: const Text("Downloading..."),
          content: Column(
            mainAxisSize: MainAxisSize.min,
            children: const [
              CircularProgressIndicator(),
              SizedBox(height: 10),
              Text("Please wait while the audio is being downloaded."),
            ],
          ),
        );
      },
    );

    // Fetch the manifest and get the highest bitrate audio stream
    var manifest = await yt.videos.streamsClient.getManifest(id);
    var streamInfo = manifest.audioOnly.withHighestBitrate();
    if (streamInfo != null) {
      // Log stream information
      print("Stream info: $streamInfo");

      // Get the actual stream
      var stream = await yt.videos.streamsClient.get(streamInfo);

      // Determine the appropriate directory
      Directory? baseDir;
      if (Platform.isAndroid) {
        baseDir = await getExternalStorageDirectory();
      } else {
        baseDir = await getApplicationDocumentsDirectory();
      }
      if (baseDir == null) {
        throw Exception("Unable to determine base directory.");
      }

      // Create the Download folder if it doesn't exist
      final downloadDir = Directory(p.join(baseDir.path, "Download"));
      if (!await downloadDir.exists()) {
        await downloadDir.create(recursive: true);
      }

      // Sanitize the file name to avoid invalid characters
      final sanitizedAdi = adi.replaceAll(RegExp(r'[<>:"/\\|?*]'), '_');

      // Construct the file path
      final filePath = p.join(downloadDir.path, "$sanitizedAdi.mp3");

      // Open the file for writing
      final file = File(filePath);
      final fileStream = file.openWrite();

      // Log when file is opened
      print("File opened: $filePath");

      // Pipe the stream directly into the file
      await stream.pipe(fileStream);
      print("Stream piped to file");

      // Ensure all data is written to the file and close the file stream
      await fileStream.flush();
      await fileStream.close();

      // Check if file size is greater than 0 to confirm the download was successful
      final fileLength = await file.length();
      if (fileLength > 0) {
        print("File saved successfully.");
        Navigator.of(context).pop(); // Dismiss progress dialog
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: const Text("Done"),
            content: Text("$sanitizedAdi.mp3 was saved to the Download folder."),
            actions: [
              ElevatedButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          ),
        );
      } else {
        // If the file is empty, show an error
        print("File is empty.");
        Navigator.of(context).pop(); // Dismiss progress dialog
        showDialog(
          context: context,
          builder: (context) => AlertDialog(
            title: const Text("Error"),
            content: const Text("Failed to download. The file is empty."),
            actions: [
              ElevatedButton(
                child: const Text('OK'),
                onPressed: () {
                  Navigator.of(context).pop();
                },
              ),
            ],
          ),
        );
      }
    } else {
      throw Exception("No audio stream found.");
    }
  } catch (e) {
    // Show error dialog
    Navigator.of(context).pop(); // Dismiss progress dialog
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text("Error"),
        content: Text("Failed to download: $e"),
        actions: [
          ElevatedButton(
            child: const Text('OK'),
            onPressed: () {
              Navigator.of(context).pop();
            },
          ),
        ],
      ),
    );
  }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants