Flutter sound package file save and post api

22 views Asked by At

im currently developing a music detector based on shazam api on rapid api. When i use .mp3 file from assets, the HTTP response works well. but when i use the file saved by the recorder, the response look like this

{"location":{"accuracy":0.01},"matches":[],"tagid":"5F410A1F-49B5-42AB-BC28-8E03D8FD1476","timestamp":1561151162,"timezone":"Europe/Moscow"}

The api is here: Shazam Recognition. Here is my code: shazam.dart


class Shazam extends StatefulWidget {
  const Shazam({super.key});

  @override
  State<Shazam> createState() => _MyWidgetState();
}

class _MyWidgetState extends State<Shazam> {
  bool isListening = false;
  final recorder = FlutterSoundRecorder();
  bool isRecorderReady = false;
  String audioPath = '';

  ResultSong song = ResultSong(name: '', images: '', artist: '');

  Future<void> fetchSong() async {
    final audioFile = File(audioPath);
    final song = await SongApi.getRecipe(audioFile);
    setState(() {
      this.song = song[0];
      log(song.toString());
    });
  }

  @override
  void initState() {
    initRecorder();
    super.initState();
  }

  @override
  void dispose() {
    recorder.closeRecorder();
    super.dispose();
  }

  Future<void> start() async {
    if (!isRecorderReady) {
      return;
    }
    await recorder.startRecorder(toFile: 'audio');
  }

  Future stop() async {
    if (!isRecorderReady) {
      return;
    }
    final path = await recorder.stopRecorder();
    setState(() {
      audioPath = path!;
    });
    fetchSong();
  }

  Future<void> initRecorder() async {
    final status = await Permission.microphone.request();

    if (status != PermissionStatus.granted) {
      throw RecordingPermissionException('Microphone permission not granted');
    }

    await recorder.openRecorder();
    isRecorderReady = true;
    recorder.setSubscriptionDuration(const Duration(milliseconds: 500));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(children: [
        Center(
          child: Column(
            children: <Widget>[
              AvatarGlow(
                  animate: isListening,
                  child: GestureDetector(
                    onTap: () async {
                      if (recorder.isRecording) {
                        await stop();
                        setState(() {
                          isListening = false;
                        });
                      } else {
                        await start();
                        setState(() {
                          isListening = true;
                        });
                      }
                    },
                    child: Container(
                      height: 200,
                      width: 200,
                      padding: const EdgeInsets.all(40),
                      decoration: const BoxDecoration(
                        shape: BoxShape.circle,
                      ),
                      child: Image.asset('assets/icon.png'),
                    ),
                  )),
              IconButton(
                onPressed: () {
                  Navigator.pushNamed(context, '/result', arguments: song);
                },
                icon: const Icon(Icons.close, color: Colors.white),
              ),
            ],
          ),
        ),
      ]),
    );
  }
}

post_song_api.dart

import 'dart:convert';
import 'dart:io';
import 'package:flutter/services.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'song_recognized.dart';

import 'dart:developer';

Future<File> getFileFromAssets(String path) async {
  final byteData = await rootBundle.load('assets/$path');

  final file = File('${(await getTemporaryDirectory()).path}/$path');
  await file.create(recursive: true);
  await file.writeAsBytes(byteData.buffer
      .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes));

  return file;
}
//the audioFile is the successful responded post API and file is the one generated by recorder.
class SongApi {
  static Future<List<ResultSong>> getRecipe(File file) async {

    File audioFile = await getFileFromAssets('audios/TTL.mp3');

    var uri = Uri.https(
        'shazam-song-recognition-api.p.rapidapi.com', '/recognize/file');
    final response = await http.post(
      uri,
      headers: {
        "content-type": "application/octet-stream",
        "x-rapidapi-key": "my_api_key",
        "x-rapidapi-host": "shazam-song-recognition-api.p.rapidapi.com",
      },
//I change the file in here to test.
      body: await file.readAsBytes(),
    );
    log(response.body);
    Map data = jsonDecode(response.body);
    List temp = [];
    temp.add(data['track']);
    return ResultSong.recipesFromSnapshot(temp);
  }
}

Im thinking about 2 ways:

  • The first one is because of the api doesn't support this file type (although i didn't know what it is) so the api refuse. Their docs says only accept (mp3/ogg/wav).
  • The second one, I think something happened with the file path or i pass it to the HTTP request body wrong way using file.readAsBytes(). I did test the recorded file in another project and it is completely normal and playable. Really appreciate any help!
0

There are 0 answers