Borewit / music-metadata

Stream and file based music metadata parser for node. Supporting a wide range of audio and tag formats.
MIT License
983 stars 93 forks source link

TypeError: (0 , music_metadata_1.parseBuffer) is not a function #2256

Closed vend1k12 closed 1 month ago

vend1k12 commented 1 month ago

Is there an existing issue for this?

music-metadata version

10.5.0

Current Behavior

While running the function to check the duration time of an audio file, the TypeError: (0 , music_metadata_1.parseBuffer) is not a function appears.

Tried using yarn, npm, pnpm but there is no difference. It doesn't matter what file I load and what type of file it is (mp3, wav, flac), and it doesn't matter what function I use (parseBuffer, parseFile, parseBlob etc). I am using Nestjs and here is the file where the error is made, as well as package.json

tracks.service.ts

import { Injectable, NotFoundException } from '@nestjs/common'
import { InjectRepository } from '@nestjs/typeorm'
import * as mm from 'music-metadata'
import { Repository } from 'typeorm'

import { Release } from '@/r/releases/entities/release.entity'

import { UpdateTrackDto } from './dto/update-track.dto'
import { Track } from './entities/track.entity'

@Injectable()
export class TracksService {
    constructor(
        @InjectRepository(Track)
        private readonly trackRepository: Repository<Track>,
        @InjectRepository(Release)
        private readonly releaseRepository: Repository<Release>
    ) {}

    async createTrack(
        file: Express.Multer.File,
        releaseId: string,
        userId: string,
        url: string
    ) {
        const release = await this.releaseRepository.findOne({
            where: { id: parseFloat(releaseId) }
        })
        if (!release) {
            throw new NotFoundException('Release not found')
        }

        const decodedName = Buffer.from(file.originalname, 'latin1').toString(
            'utf8'
        )

        console.log(decodedName)

        const duration = await this.getAudioDuration(file.buffer, file.mimetype)

        const track = this.trackRepository.create({
            release,
            audio: url,
            originalName: decodedName,
            duration,
            title: decodedName
        })

        return await this.trackRepository.save(track)
    }

    async getAudioDuration(
        buffer: Uint8Array,
        mimeType: string
    ): Promise<number> {
        console.log(buffer)
        try {
            const metadata = await mm.parseBuffer(
                buffer,
                { mimeType },
                { duration: true }
            )
            return metadata.format.duration
        } catch (error) {
            console.error('Error while parsing audio metadata:', error)
            throw new Error('Error while parsing audio metadata')
        }
    }

    async updateTrack(trackId: number, releaseId: number, dto: UpdateTrackDto) {
        const track = await this.trackRepository.findOne({ where: { id: trackId } })
        if (!track) {
            throw new NotFoundException('Track not found')
        }
        const release = await this.releaseRepository.findOne({
            where: { id: releaseId }
        })
        if (!release) {
            throw new NotFoundException('Release not found')
        }
        return await this.trackRepository.save({ ...track, ...dto, release })
    }

    async deleteTrack(trackId: number) {
        const track = await this.trackRepository.findOne({ where: { id: trackId } })
        if (!track) {
            throw new NotFoundException('Track not found')
        }

        return await this.trackRepository.remove(track)
    }
}

package,json

    "name": "api-v2",
    "version": "2.0.0@beta.4",
    "description": "REST API v2",
    "private": true,
    "license": "Apache-2.0",
    "packageManager": "yarn@1.22.22",
    "scripts": {
        "build": "nest build",
        "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
        "start:prod": "node dist/src/main",
        "start": "nest start",
        "dev": "nest start --watch",
        "email:dev": "email dev -p 2016",
        "start:debug": "nest start --debug --watch",
        "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix",
        "test": "jest",
        "test:watch": "jest --watch",
        "test:cov": "jest --coverage",
        "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
        "test:e2e": "jest --config ./test/jest-e2e.json"
    },
    "dependencies": {
        "@aws-sdk/client-s3": "^3.645.0",
        "@aws-sdk/s3-request-presigner": "^3.645.0",
        "@nestjs-modules/mailer": "^2.0.2",
        "@nestjs/axios": "^3.0.3",
        "@nestjs/common": "^10.4.1",
        "@nestjs/config": "^3.2.3",
        "@nestjs/core": "^10.4.1",
        "@nestjs/jwt": "^10.2.0",
        "@nestjs/passport": "^10.0.3",
        "@nestjs/platform-express": "^10.4.1",
        "@nestjs/typeorm": "^10.0.2",
        "@react-email/components": "0.0.22",
        "@react-email/font": "0.0.8",
        "@react-email/render": "^0.0.17",
        "axios": "^1.7.7",
        "bcrypt": "^5.1.1",
        "class-transformer": "^0.5.1",
        "class-validator": "^0.14.1",
        "cookie-parser": "^1.4.6",
        "generate-password-ts": "^1.6.5",
        "i18next": "^23.15.1",
        "multer": "1.4.5-lts.1",
        "music-metadata": "^10.5.0",
        "nestjs-i18n": "^10.4.8",
        "nodemailer": "^6.9.14",
        "otplib": "^12.0.1",
        "passport": "^0.7.0",
        "passport-jwt": "^4.0.1",
        "pg": "^8.12.0",
        "qrcode": "^1.5.4",
        "react": "^18.3.1",
        "react-dom": "^18.3.1",
        "react-email": "2.1.6",
        "reflect-metadata": "^0.2.2",
        "rxjs": "^7.8.1",
        "speakeasy": "^2.0.0",
        "typeorm": "^0.3.20",
        "typeorm-extension": "^3.6.1"
    },
    "devDependencies": {
        "@faker-js/faker": "^9.0.0",
        "@nestjs/cli": "^10.4.5",
        "@nestjs/schematics": "^10.1.4",
        "@nestjs/testing": "^10.4.1",
        "@trivago/prettier-plugin-sort-imports": "^4.3.0",
        "@types/bcrypt": "^5.0.2",
        "@types/cookie-parser": "^1.4.7",
        "@types/express": "^4.17.21",
        "@types/jest": "^29.5.12",
        "@types/multer": "^1.4.12",
        "@types/node": "^22.5.4",
        "@types/nodemailer": "^6.4.15",
        "@types/passport-jwt": "^4.0.1",
        "@types/qrcode": "^1.5.5",
        "@types/react": "^18.3.5",
        "@types/speakeasy": "^2.0.10",
        "@types/supertest": "^6.0.2",
        "@types/uuid": "^10.0.0",
        "@typescript-eslint/eslint-plugin": "^8.5.0",
        "@typescript-eslint/parser": "^8.5.0",
        "eslint": "^9.10.0",
        "eslint-config-prettier": "^9.1.0",
        "eslint-plugin-prettier": "^5.2.1",
        "jest": "^29.7.0",
        "prettier": "^3.3.3",
        "source-map-support": "^0.5.21",
        "supertest": "^7.0.0",
        "ts-jest": "^29.2.5",
        "ts-loader": "^9.5.1",
        "ts-node": "^10.9.2",
        "tsconfig-paths": "^4.2.0",
        "tsx": "^4.19.0",
        "typescript": "^5.6.2"
    },
    "jest": {
        "moduleFileExtensions": [
            "js",
            "json",
            "ts"
        ],
        "rootDir": "src",
        "testRegex": ".*\\.spec\\.ts$",
        "transform": {
            "^.+\\.(t|j)s$": "ts-jest"
        },
        "collectCoverageFrom": [
            "**/*.(t|j)s"
        ],
        "coverageDirectory": "../coverage",
        "testEnvironment": "node"
    },
    "resolutions": {
        "wrap-ansi": "7.0.0",
        "string-width": "4.1.0"
    }
}

Expected Behavior

No response

Attached audio sample?

vend1k12 commented 1 month ago

By the way yes, I've tried several import options. import * as mm from 'music-metadata' and import { parseBuffer } from 'music-metadata', but there is no difference.

Borewit commented 1 month ago

Note that this is an ESM module, check CommonJS backward compatibility or better, switch your project to ESM, and imports shall work as you initially expected.

vend1k12 commented 1 month ago

Oh, thanks a lot, somehow I missed that point in the documentation <з