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: Fix audio file with cover image treated as video file #91

34 changes: 24 additions & 10 deletions MediaProcessor/src/Engine.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "Engine.h"

#include <iostream>
#include <nlohmann/json.hpp>

#include "AudioProcessor.h"
#include "ConfigManager.h"
Expand Down Expand Up @@ -65,23 +66,36 @@ bool Engine::processVideo() {

MediaType Engine::getMediaType() const {
const std::string command =
"ffprobe -loglevel error -show_entries stream=codec_type "
"-of default=noprint_wrappers=1:nokey=1 \"" +
m_mediaPath.string() + "\"";
"ffprobe -loglevel error -show_entries stream -of json \"" + m_mediaPath.string() + "\"";

std::optional<std::string> output = Utils::runCommand(command, true);
if (!output || output->empty()) {
throw std::runtime_error("Failed to detect media type.");
}

std::string_view result = *output;
if (result.find("video") != std::string_view::npos) {
return MediaType::Video;
} else if (result.find("audio") != std::string_view::npos) {
return MediaType::Audio;
} else {
throw std::runtime_error("Unsupported media type detected.");
nlohmann::json streamData = nlohmann::json::parse(*output);

int videoStreamCount{0}, audioStreamCount{0};
for (const auto& stream : streamData["streams"]) {
if (stream["codec_type"] == "video") {
++videoStreamCount;

if (videoStreamCount > 1) {
return MediaType::Video;
}

std::vector<int> frameRate = Utils::parseFrameRate(stream["avg_frame_rate"]);
if (frameRate[0] != 0 || frameRate[1] != 0) {
return MediaType::Video;
}
} else if (stream["codec_type"] == "audio") {
++audioStreamCount;
} else {
throw std::runtime_error("Unsupported media type detected.");
}
}

return audioStreamCount ? MediaType::Audio : MediaType::Unsupported;
}

} // namespace MediaProcessor
25 changes: 25 additions & 0 deletions MediaProcessor/src/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,31 @@ std::string enumToString(const T& value, const std::unordered_map<T, std::string
return (it != valueMap.end()) ? it->second : "unknown";
}

std::vector<int> parseFrameRate(const std::string& frameRate) {
std::vector<int> result;
result.reserve(2);

std::istringstream stream(frameRate);
std::string token;

while(std::getline(stream, token, '/')) {
try {
result.push_back(std::stoi(token));
} catch (const std::invalid_argument&) {
throw std::runtime_error("Invalid avg_frame_rate value: " + frameRate);
} catch (const std::out_of_range&) {
throw std::runtime_error("Out-of-range value in avg_frame_rate: " + frameRate);
}
}

// Ensure the result contains exactly 2 elements (numerator and denominator)
if (result.size() != 2) {
throw std::runtime_error("avg_frame_rate does not have two components: " + frameRate);
}

return result;
}

// Explicit instantiations ensure the compiler generates the template for a type
template std::string enumToString<AudioCodec>(
const AudioCodec& codec, const std::unordered_map<AudioCodec, std::string>& codecMap);
Expand Down
8 changes: 8 additions & 0 deletions MediaProcessor/src/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>

namespace fs = std::filesystem;

Expand Down Expand Up @@ -112,6 +113,13 @@ bool isWithinRange(T value, T lowerBound, T upperBound) {
template <typename T>
std::string enumToString(const T& value, const std::unordered_map<T, std::string>& valueMap);

/**
* @brief Parses the given frame rate(from string) and returns the frame rate in vector<int>
*
* @return vector<int> of size 2, which contains frame rate.
*/
std::vector<int> parseFrameRate(const std::string& frameRate);

} // namespace MediaProcessor::Utils

#endif // UTILS_H