ffmpeg переобожмёт во всех подкаталогах

Ответить
ya
^-^
Сообщения: 2336
Зарегистрирован: 16 дек 2021, 19:56

ffmpeg переобожмёт во всех подкаталогах

Сообщение ya »

Код: Выделить всё

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <cmath>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <array> 
#include <sstream>
#include <algorithm>
#include <sys/stat.h>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif


struct VideoInfo
{
    double total_duration;
    unsigned long int total_size;
    int total_bit_rate;
    std::pair<int, int> resolution;
    std::string aspect_ratio;
};

bool isValidNumber(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(),
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

bool file_exists(const std::string& filepath) {
    struct stat buffer;
    return (stat(filepath.c_str(), &buffer) == 0);
}

#ifdef _WIN32
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = _popen(cmd.c_str(), "rb");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = _pclose(fp);
        
        if (exit_code == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(exit_code));
        }
    }
#else
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = popen(cmd.c_str(), "r");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = pclose(fp);
        
        if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(WEXITSTATUS(exit_code)));
        }
    }
#endif

std::string get_aspect_ratio(const double aspect_ratio)
{
    int approx_ratio = static_cast<int>(std::round(aspect_ratio));
    switch (approx_ratio)
    {
        case 1:
            return "1:1";
        case 4:
            return "4:3";
        case 5:
            return "5:4";
        case 16:
            return "16:9";
        case 17:
            return "17:10";
        case 21:
            return "21:9";
        default:
            return std::to_string(approx_ratio);
    }
}

VideoInfo get_video_info(const std::string& input)
{
    std::string command = "ffprobe -v error -show_entries format=size,duration,bit_rate:stream=codec_type,width,height,bit_rate,display_aspect_ratio -of default=noprint_wrappers=1 -i \"" + input + "\"";
    std::istringstream ffprobe_pipe(run_command(command));
    
    std::unordered_map<std::string, std::string> info_map;
    std::string line;
    while (std::getline(ffprobe_pipe, line))
    {
        size_t pos = line.find('=');
        if (pos != std::string::npos)
        {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);

            if (value != "N/A")
            {
                info_map[key] = value;
            }
        }
    }

    VideoInfo info;
    info.total_duration = std::stod(info_map["duration"]);
	/*if (isValidNumber(info_map["size"]))
	{
		long double result;// = std::stoi(info_map["size"]);
    // ... используйте результат, если строки валидны
	}
	else
	{
    // обработка ошибки: ваша строка не является корректным числом
		throw std::invalid_argument("Invalid argument: size " + info_map["size"]);
	}*/
    //info.total_size = std::stoi(info_map["size"]);
    info.total_bit_rate = std::stoi(info_map["bit_rate"]);
    info.resolution = std::make_pair(std::stoi(info_map["width"]), std::stoi(info_map["height"]));
    double dar = std::stod(info_map["display_aspect_ratio"]);
    info.aspect_ratio = get_aspect_ratio(dar);
    
    return info;
}

std::string format_duration(double duration) 
{
    int hours = static_cast<int>(duration / 3600);
    duration -= hours * 3600;
    int minutes = static_cast<int>(duration / 60);
    duration -= minutes * 60;
    int seconds = static_cast<int>(duration);

    std::ostringstream formatted_duration;
    formatted_duration << std::setfill('0') << std::setw(2) << hours << ":"
                       << std::setw(2) << minutes << ":"
                       << std::setw(2) << seconds;

    return formatted_duration.str();
}

void set_input_file(const std::string& input_path)
{
    VideoInfo video_info = get_video_info(input_path);
	
	std::string formatted_duration = format_duration(video_info.total_duration);

    std::cout << "Duration: " << formatted_duration << " " << std::endl;
    //std::cout << "Size: " << video_info.total_size << " byte" << std::endl;
    std::cout << "Total bitrate: " << (ceil(video_info.total_bit_rate/(1000*100))/10) << " Mbps" << std::endl;
    std::cout << "Resolution: " << video_info.resolution.first << "x" << video_info.resolution.second << std::endl;
    std::cout << "Aspect ratio: " << video_info.aspect_ratio << std::endl;

}



/*
if (isValidNumber(your_string))
{
    int result = std::stoi(your_string);
    // ... используйте результат, если строки валидны
}
else
{
    // обработка ошибки: ваша строка не является корректным числом
    throw std::invalid_argument("Invalid argument: " + your_string);
}
*/



std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v"};


std::string format_ffmpeg(const std::string& input_path)
{
	VideoInfo video_info = get_video_info(input_path);
	std::ostringstream formatted_ffmpeg;
   
	if((video_info.resolution.second >= 1080) && (video_info.resolution.first > 1280))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if(((ceil(video_info.total_bit_rate/(1000*100))/10) > 8.1) || ((ceil(video_info.total_bit_rate/(1000*100))/10) < 5))
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "8M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1920x1080"; 
	}
	else if ((video_info.resolution.first == 1280)&& (video_info.resolution.second == 720))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if((ceil(video_info.total_bit_rate/(1000*100))/10) > 5.3)
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "5M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1280x720"; 
		
	}
	else
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v 5M "; 
	}
	
    //formatted_ffmpeg << std::setfill('0') << std::setw(2) << s;

    return formatted_ffmpeg.str();
}


void convert_video(const std::string& input_path)
{
    const auto last_dot_index = input_path.find_last_of('.');
    std::string output_path = input_path.substr(0, last_dot_index) + ".mp4";
	
	std::string command = "ffmpeg -i \"" + input_path; 
	command += "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -c:v libx264 ";
	command += format_ffmpeg(input_path) + " -r 29.97 -c:a ";
#ifdef _WIN32
	command += "libvo_aacenc";
#else
	command += "aac";
#endif
	command += " -b:a 320K  \""+ output_path + "\"";
    std::cout << "command: " << command << std::endl;
	std::cout << std::endl;
	
	system(command.c_str());
}

// Включайте все заголовки, как указано в вашем исходном коде

// Используйте функции: run_command, get_aspect_ratio, get_video_info,
// set_input_file, format_duration, format_ffmpeg, convert_video, как и в вашем исходном коде


bool is_directory(const std::string& directory_path, dirent* entry)
{
#ifdef _DIRENT_HAVE_D_TYPE
    return entry->d_type == DT_DIR;
#else
    struct stat path_stat;
    std::string full_path = directory_path + "/" + entry->d_name;
    if (stat(full_path.c_str(), &path_stat) == 0)
    {
        return S_ISDIR(path_stat.st_mode);
    }
    else
    {
        return false;
    }
#endif
}


void traverse_directory(const std::string& directory_path)
{
    DIR* dir;
    dirent* entry;

    if ((dir = opendir(directory_path.c_str())) != nullptr)
    {
        while ((entry = readdir(dir)) != nullptr)
        {
            if (is_directory(directory_path, entry))
            {
                std::string sub_directory = entry->d_name;

                if (sub_directory != "." && sub_directory != "..")
                {
                    traverse_directory(directory_path + "/" + sub_directory);
                }
            }
            else
            {
                const std::string entry_name = entry->d_name;
                const auto ext_start = entry_name.find_last_of('.');

                if (ext_start != std::string::npos)
                {
                    const std::string ext = entry_name.substr(ext_start);

                    if (std::find(valid_extensions.begin(), valid_extensions.end(), std::string(ext)) != valid_extensions.end())
                    {
                        std::string file_path = directory_path + "/" + entry_name;

                        std::cout << "Converting video file: " << file_path << std::endl;
                        set_input_file(file_path);
                        convert_video(file_path);
                    }
                }
            }
        }
        closedir(dir);
    }
}


int main()
{
    std::string start_directory = ".";  // Задайте стартовый каталог (или измените на нужный)
    traverse_directory(start_directory);

    return 0;
}
es_
Батько
Сообщения: 23
Зарегистрирован: 16 дек 2021, 08:29

Перекодирует и удалит исходный файл

Сообщение es_ »

Код: Выделить всё

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <cmath>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <array> 
#include <sstream>
#include <algorithm>
#include <sys/stat.h>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif


struct VideoInfo
{
    double total_duration;
    unsigned long int total_size;
    int total_bit_rate;
    std::pair<int, int> resolution;
    std::string aspect_ratio;
};

bool isValidNumber(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(),
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

bool file_exists(const std::string& filepath) {
    struct stat buffer;
    return (stat(filepath.c_str(), &buffer) == 0);
}

#ifdef _WIN32
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = _popen(cmd.c_str(), "rb");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = _pclose(fp);
        
        if (exit_code == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(exit_code));
        }
    }
#else
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = popen(cmd.c_str(), "r");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = pclose(fp);
        
        if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(WEXITSTATUS(exit_code)));
        }
    }
#endif

std::string get_aspect_ratio(const double aspect_ratio)
{
    int approx_ratio = static_cast<int>(std::round(aspect_ratio));
    switch (approx_ratio)
    {
        case 1:
            return "1:1";
        case 4:
            return "4:3";
        case 5:
            return "5:4";
        case 16:
            return "16:9";
        case 17:
            return "17:10";
        case 21:
            return "21:9";
        default:
            return std::to_string(approx_ratio);
    }
}

VideoInfo get_video_info(const std::string& input)
{
    std::string command = "ffprobe -v error -show_entries format=size,duration,bit_rate:stream=codec_type,width,height,bit_rate,display_aspect_ratio -of default=noprint_wrappers=1 -i \"" + input + "\"";
    std::istringstream ffprobe_pipe(run_command(command));
    
    std::unordered_map<std::string, std::string> info_map;
    std::string line;
    while (std::getline(ffprobe_pipe, line))
    {
        size_t pos = line.find('=');
        if (pos != std::string::npos)
        {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);

            if (value != "N/A")
            {
                info_map[key] = value;
            }
        }
    }

    VideoInfo info;
    info.total_duration = std::stod(info_map["duration"]);
	/*if (isValidNumber(info_map["size"]))
	{
		long double result;// = std::stoi(info_map["size"]);
    // ... используйте результат, если строки валидны
	}
	else
	{
    // обработка ошибки: ваша строка не является корректным числом
		throw std::invalid_argument("Invalid argument: size " + info_map["size"]);
	}*/
    //info.total_size = std::stoi(info_map["size"]);
    info.total_bit_rate = std::stoi(info_map["bit_rate"]);
    info.resolution = std::make_pair(std::stoi(info_map["width"]), std::stoi(info_map["height"]));
    double dar = std::stod(info_map["display_aspect_ratio"]);
    info.aspect_ratio = get_aspect_ratio(dar);
    
    return info;
}

std::string format_duration(double duration) 
{
    int hours = static_cast<int>(duration / 3600);
    duration -= hours * 3600;
    int minutes = static_cast<int>(duration / 60);
    duration -= minutes * 60;
    int seconds = static_cast<int>(duration);

    std::ostringstream formatted_duration;
    formatted_duration << std::setfill('0') << std::setw(2) << hours << ":"
                       << std::setw(2) << minutes << ":"
                       << std::setw(2) << seconds;

    return formatted_duration.str();
}

void set_input_file(const std::string& input_path)
{
    VideoInfo video_info = get_video_info(input_path);
	
	std::string formatted_duration = format_duration(video_info.total_duration);

    std::cout << "Duration: " << formatted_duration << " " << std::endl;
    //std::cout << "Size: " << video_info.total_size << " byte" << std::endl;
    std::cout << "Total bitrate: " << (ceil(video_info.total_bit_rate/(1000*100))/10) << " Mbps" << std::endl;
    std::cout << "Resolution: " << video_info.resolution.first << "x" << video_info.resolution.second << std::endl;
    std::cout << "Aspect ratio: " << video_info.aspect_ratio << std::endl;

}



/*
if (isValidNumber(your_string))
{
    int result = std::stoi(your_string);
    // ... используйте результат, если строки валидны
}
else
{
    // обработка ошибки: ваша строка не является корректным числом
    throw std::invalid_argument("Invalid argument: " + your_string);
}
*/



std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v"};


std::string format_ffmpeg(const std::string& input_path)
{
	VideoInfo video_info = get_video_info(input_path);
	std::ostringstream formatted_ffmpeg;
   
	if((video_info.resolution.second >= 1080) && (video_info.resolution.first > 1280))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if(((ceil(video_info.total_bit_rate/(1000*100))/10) > 8.1) || ((ceil(video_info.total_bit_rate/(1000*100))/10) < 5))
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "8M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1920x1080"; 
	}
	else if ((video_info.resolution.first == 1280)&& (video_info.resolution.second == 720))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if((ceil(video_info.total_bit_rate/(1000*100))/10) > 5.3)
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "5M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1280x720"; 
		
	}
	else
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v 5M "; 
	}
	
    //formatted_ffmpeg << std::setfill('0') << std::setw(2) << s;

    return formatted_ffmpeg.str();
}


void convert_video(const std::string& input_path)
{
    const auto last_dot_index = input_path.find_last_of('.');
    std::string output_path = input_path.substr(0, last_dot_index) + ".mp4";
	
	std::string command = "ffmpeg -i \"" + input_path; 
	command += "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -c:v libx264 ";
	command += format_ffmpeg(input_path) + " -r 29.97 -c:a ";
#ifdef _WIN32
	command += "libvo_aacenc";
#else
	command += "aac";
#endif
	command += " -b:a 320K -n \""+ output_path + "\"";
    std::cout << "command: " << command << std::endl;
	std::cout << std::endl;
	
	system(command.c_str());

	// Удалит входной файл после обработки
	std::string command_rm_input_path = "";
#ifdef _WIN32
    system("timeout /t 2");
	command_rm_input_path = "DEL /Q \"" + input_path +"\"";
#else
    system("sleep 2");
	command_rm_input_path = "rm -y \"" + input_path + "\"";
#endif
	system(command_rm_input_path.c_str());
}

// Включайте все заголовки, как указано в вашем исходном коде

// Используйте функции: run_command, get_aspect_ratio, get_video_info,
// set_input_file, format_duration, format_ffmpeg, convert_video, как и в вашем исходном коде


bool is_directory(const std::string& directory_path, dirent* entry)
{
#ifdef _DIRENT_HAVE_D_TYPE
    return entry->d_type == DT_DIR;
#else
    struct stat path_stat;
    std::string full_path = directory_path + "/" + entry->d_name;
    if (stat(full_path.c_str(), &path_stat) == 0)
    {
        return S_ISDIR(path_stat.st_mode);
    }
    else
    {
        return false;
    }
#endif
}


void traverse_directory(const std::string& directory_path)
{
    DIR* dir;
    dirent* entry;

    if ((dir = opendir(directory_path.c_str())) != nullptr)
    {
        while ((entry = readdir(dir)) != nullptr)
        {
            if (is_directory(directory_path, entry))
            {
                std::string sub_directory = entry->d_name;

                if (sub_directory != "." && sub_directory != "..")
                {
                    traverse_directory(directory_path + "/" + sub_directory);
                }
            }
            else
            {
                const std::string entry_name = entry->d_name;
                const auto ext_start = entry_name.find_last_of('.');

                if (ext_start != std::string::npos)
                {
                    const std::string ext = entry_name.substr(ext_start);

                    if (std::find(valid_extensions.begin(), valid_extensions.end(), std::string(ext)) != valid_extensions.end())
                    {
                        std::string file_path = directory_path + "/" + entry_name;

                        std::cout << "Converting video file: " << file_path << std::endl;
                        set_input_file(file_path);
                        convert_video(file_path);
                    }
                }
            }
        }
        closedir(dir);
    }
}


int main()
{
    std::string start_directory = ".";  // Задайте стартовый каталог (или измените на нужный)
    traverse_directory(start_directory);

    return 0;
}

ya
^-^
Сообщения: 2336
Зарегистрирован: 16 дек 2021, 19:56

Re: ffmpeg переобожмёт во всех подкаталогах

Сообщение ya »

g++ -o encdel -std=c++11 encdel.cpp

./encdel
ya
^-^
Сообщения: 2336
Зарегистрирован: 16 дек 2021, 19:56

Re: ffmpeg переобожмёт во всех подкаталогах

Сообщение ya »

Код: Выделить всё

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <cmath>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <array> 
#include <sstream>
#include <algorithm>
#include <sys/stat.h>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif


struct VideoInfo
{
    double total_duration;
    unsigned long int total_size;
    int total_bit_rate;
    std::pair<int, int> resolution;
    std::string aspect_ratio;
};

bool isValidNumber(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(),
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

bool file_exists(const std::string& filepath) {
    struct stat buffer;
    return (stat(filepath.c_str(), &buffer) == 0);
}

#ifdef _WIN32
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = _popen(cmd.c_str(), "rb");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = _pclose(fp);
        
        if (exit_code == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(exit_code));
        }
    }
#else
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = popen(cmd.c_str(), "r");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = pclose(fp);
        
        if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(WEXITSTATUS(exit_code)));
        }
    }
#endif

std::string get_aspect_ratio(const double aspect_ratio)
{
    int approx_ratio = static_cast<int>(std::round(aspect_ratio));
    switch (approx_ratio)
    {
        case 1:
            return "1:1";
        case 4:
            return "4:3";
        case 5:
            return "5:4";
        case 16:
            return "16:9";
        case 17:
            return "17:10";
        case 21:
            return "21:9";
        default:
            return std::to_string(approx_ratio);
    }
}

VideoInfo get_video_info(const std::string& input)
{
    std::string command = "ffprobe -v error -show_entries format=size,duration,bit_rate:stream=codec_type,width,height,bit_rate,display_aspect_ratio -of default=noprint_wrappers=1 -i \"" + input + "\"";
    std::istringstream ffprobe_pipe(run_command(command));
    
    std::unordered_map<std::string, std::string> info_map;
    std::string line;
    while (std::getline(ffprobe_pipe, line))
    {
        size_t pos = line.find('=');
        if (pos != std::string::npos)
        {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);

            if (value != "N/A")
            {
                info_map[key] = value;
            }
        }
    }

    VideoInfo info;
    info.total_duration = std::stod(info_map["duration"]);
	/*if (isValidNumber(info_map["size"]))
	{
		long double result;// = std::stoi(info_map["size"]);
    // ... используйте результат, если строки валидны
	}
	else
	{
    // обработка ошибки: ваша строка не является корректным числом
		throw std::invalid_argument("Invalid argument: size " + info_map["size"]);
	}*/
    //info.total_size = std::stoi(info_map["size"]);
    info.total_bit_rate = std::stoi(info_map["bit_rate"]);
    info.resolution = std::make_pair(std::stoi(info_map["width"]), std::stoi(info_map["height"]));
    double dar = std::stod(info_map["display_aspect_ratio"]);
    info.aspect_ratio = get_aspect_ratio(dar);
    
    return info;
}

std::string format_duration(double duration) 
{
    int hours = static_cast<int>(duration / 3600);
    duration -= hours * 3600;
    int minutes = static_cast<int>(duration / 60);
    duration -= minutes * 60;
    int seconds = static_cast<int>(duration);

    std::ostringstream formatted_duration;
    formatted_duration << std::setfill('0') << std::setw(2) << hours << ":"
                       << std::setw(2) << minutes << ":"
                       << std::setw(2) << seconds;

    return formatted_duration.str();
}

void set_input_file(const std::string& input_path)
{
    VideoInfo video_info = get_video_info(input_path);
	
	std::string formatted_duration = format_duration(video_info.total_duration);

    std::cout << "Duration: " << formatted_duration << " " << std::endl;
    //std::cout << "Size: " << video_info.total_size << " byte" << std::endl;
    std::cout << "Total bitrate: " << (ceil(video_info.total_bit_rate/(1000*100))/10) << " Mbps" << std::endl;
    std::cout << "Resolution: " << video_info.resolution.first << "x" << video_info.resolution.second << std::endl;
    std::cout << "Aspect ratio: " << video_info.aspect_ratio << std::endl;

}



/*
if (isValidNumber(your_string))
{
    int result = std::stoi(your_string);
    // ... используйте результат, если строки валидны
}
else
{
    // обработка ошибки: ваша строка не является корректным числом
    throw std::invalid_argument("Invalid argument: " + your_string);
}
*/



std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v", ".VOB"};


std::string format_ffmpeg(const std::string& input_path)
{
	VideoInfo video_info = get_video_info(input_path);
	std::ostringstream formatted_ffmpeg;
   
	if((video_info.resolution.second >= 1080) && (video_info.resolution.first > 1280))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if(((ceil(video_info.total_bit_rate/(1000*100))/10) > 8.1) || ((ceil(video_info.total_bit_rate/(1000*100))/10) < 5))
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "8M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1920x1080"; 
	}
	else if ((video_info.resolution.first == 1280)&& (video_info.resolution.second == 720))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if((ceil(video_info.total_bit_rate/(1000*100))/10) > 5.3)
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "5M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1280x720"; 
		
	}
	else
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v 4.5M -vf yadif -preset slow "; 
	}
	
    //formatted_ffmpeg << std::setfill('0') << std::setw(2) << s;

    return formatted_ffmpeg.str();
}


std::string slash_replace(const std::string& input_path)
{
	std::string path = input_path;
    std::cout << "Original path: " << path << std::endl;
    
    // Find and replace all slashes with backslashes
    size_t pos = 0;
    while ((pos = path.find('/', pos)) != std::string::npos) {
        path.replace(pos, 1, "\\");
        pos += 1;
    }
    
    std::cout << "Updated path: " << path << std::endl;
    
    return path;
}

void convert_video(const std::string& input_path)
{
    const auto last_dot_index = input_path.find_last_of('.');
    std::string output_path = input_path.substr(0, last_dot_index) + ".mp4";
	
	std::string command = "ffmpeg -i \"" + input_path; 
	command += "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -c:v libx264 ";
	command += format_ffmpeg(input_path) + " -r 29.97 -c:a ";
#ifdef _WIN32
	command += "libvo_aacenc";
#else
	command += "aac";
#endif
	command += " -b:a 320K -n \""+ output_path + "\"";
    std::cout << "command: " << command << std::endl;
	std::cout << std::endl;
	
	system(command.c_str());

	// Удалит входной файл после обработки
	std::string command_rm_input_path = "";
#ifdef _WIN32
    system("timeout /t 2");
	command_rm_input_path = "DEL /Q /F \"" + slash_replace(input_path) +"\"";
#else
    system("sleep 2");
	command_rm_input_path = "rm -y \"" + input_path + "\"";
#endif
	system(command_rm_input_path.c_str());
}

// Включайте все заголовки, как указано в вашем исходном коде

// Используйте функции: run_command, get_aspect_ratio, get_video_info,
// set_input_file, format_duration, format_ffmpeg, convert_video, как и в вашем исходном коде


bool is_directory(const std::string& directory_path, dirent* entry)
{
#ifdef _DIRENT_HAVE_D_TYPE
    return entry->d_type == DT_DIR;
#else
    struct stat path_stat;
    std::string full_path = directory_path + "/" + entry->d_name;
    if (stat(full_path.c_str(), &path_stat) == 0)
    {
        return S_ISDIR(path_stat.st_mode);
    }
    else
    {
        return false;
    }
#endif
}


void traverse_directory(const std::string& directory_path)
{
    DIR* dir;
    dirent* entry;

    if ((dir = opendir(directory_path.c_str())) != nullptr)
    {
        while ((entry = readdir(dir)) != nullptr)
        {
            if (is_directory(directory_path, entry))
            {
                std::string sub_directory = entry->d_name;

                if (sub_directory != "." && sub_directory != "..")
                {
                    traverse_directory(directory_path + "/" + sub_directory);
                }
            }
            else
            {
                const std::string entry_name = entry->d_name;
                const auto ext_start = entry_name.find_last_of('.');

                if (ext_start != std::string::npos)
                {
                    const std::string ext = entry_name.substr(ext_start);

                    if (std::find(valid_extensions.begin(), valid_extensions.end(), std::string(ext)) != valid_extensions.end())
                    {
                        std::string file_path = directory_path + "/" + entry_name;

                        std::cout << "Converting video file: " << file_path << std::endl;
                        set_input_file(file_path);
                        convert_video(file_path);
                    }
                }
            }
        }
        closedir(dir);
    }
}


int main()
{
    std::string start_directory = ".";  // Задайте стартовый каталог (или измените на нужный)
    traverse_directory(start_directory);

    return 0;
}

ya
^-^
Сообщения: 2336
Зарегистрирован: 16 дек 2021, 19:56

Re: ffmpeg переобожмёт во всех подкаталогах

Сообщение ya »

ffen3.cpp

Код: Выделить всё

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <array>
#include <tuple>
#include <sstream>

std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v"};
/*
std::tuple<int, std::pair<int, int>, std::pair<int, int>>
get_video_info(const std::string &input_path)
{
    std::string ffprobe_output;
    std::string command = "ffprobe -v error -show_entries stream=bit_rate,width,height,display_aspect_ratio -of default=noprint_wrappers=1 -i \"" + input_path + "\"";
    std::array<char, 128> buffer;
    FILE *pipe = popen(command.c_str(), "r");

    if (!pipe)
    {
        throw std::runtime_error("popen() failed!");
    }
    while (fgets(buffer.data(), 128, pipe) != nullptr)
    {
        ffprobe_output += buffer.data();
    }
    auto close_code = pclose(pipe);

    int bit_rate, width, height;
    std::pair<int, int> resolution, aspect;
    sscanf(ffprobe_output.c_str(), "bit_rate=%d\nwidth=%d\nheight=%d\ndisplay_aspect_ratio=%d:%d\n", &bit_rate, &width, &height, &aspect.first, &aspect.second);
    resolution = std::make_pair(width, height);

    return std::make_tuple(bit_rate, resolution, aspect);
}
*/

std::string trim(const std::string &str)
{
    size_t first = str.find_first_not_of(" \t\n\r");
    size_t last = str.find_last_not_of(" \t\n\r");

    if (std::string::npos == first || std::string::npos == last)
    {
        return "";
    }

    return str.substr(first, last - first + 1);
}


std::string sanitize_bitrate(const std::string& bitrate_str)
{
    auto pos = bitrate_str.find("kb/s");
    if (pos != std::string::npos)
    {
        return bitrate_str.substr(0, pos);
    }
    return bitrate_str;
}

std::tuple<int, std::pair<int, int>, std::pair<int, int>> get_video_info(const std::string& input_path)
{
    std::string ffprobe_output;
    std::string command = "ffprobe -v error -show_entries format=size,duration,bit_rate:stream=codec_type,bit_rate,width,height,display_aspect_ratio -of default=noprint_wrappers=1 -i \"" + input_path + "\"";
    std::array<char, 128> buffer;
    FILE *pipe = popen(command.c_str(), "r");

    if (!pipe)
    {
        throw std::runtime_error("popen() failed!");
    }
    while (fgets(buffer.data(), 128, pipe) != nullptr)
    {
        ffprobe_output += buffer.data();
    }
    auto close_code = pclose(pipe);

    // Обработка вывода ffprobe
    int video_bit_rate = 0, width = 0, height = 0, audio_bit_rate = 0;
    std::pair<int, int> resolution, aspect;
    std::istringstream iss(ffprobe_output);
    std::string line;
    std::string codec_type;
	std::string video_duration;
    /*
	while (std::getline(iss, line))
    {
        if (line.find("codec_type=") != std::string::npos)
        {
            codec_type = line.substr(line.find('=') + 1);
        }
        else if (codec_type == "video")
        {
            if (line.find("bit_rate=") != std::string::npos)
            {
                video_bit_rate = std::stoi(line.substr(line.find('=') + 1));
            }
            else if (line.find("width=") != std::string::npos)
            {
                width = std::stoi(line.substr(line.find('=') + 1));
            }
            else if (line.find("height=") != std::string::npos)
            {
                height = std::stoi(line.substr(line.find('=') + 1));
            }
            else if (line.find("display_aspect_ratio=") != std::string::npos)
            {
                sscanf(line.c_str(), "display_aspect_ratio=%d:%d", &aspect.first, &aspect.second);
            }
        }
        else if (codec_type == "audio")
        {
            if (line.find("bit_rate=") != std::string::npos)
            {
                audio_bit_rate = std::stoi(line.substr(line.find('=') + 1));
            }
        }
    }
	
	*/

while (std::getline(iss, line))
{
    if (line.find("codec_type=") != std::string::npos)
    {
        codec_type = line.substr(line.find('=') + 1);
    }
	else if (codec_type == "video")
	{
		if (line.find("bitrate:") != std::string::npos)
		{
		    // Берем общий битрейт
		    size_t bitrate_pos = line.find("bitrate:");
		    video_bit_rate = std::stoi(sanitize_bitrate(trim(line.substr(bitrate_pos + 8))));
		}
		// Выводим строку для отладки
		std::cout << "DEBUG: Duration line: " << line << std::endl;

		video_duration = line.substr(line.find("Duration") + 9,
		                              line.find(',') -
		                              (line.find("Duration") + 9));
		video_duration = trim(video_duration);

		// //

		if (line.find("bit_rate=") != std::string::npos)
		{
		    try
		    {
		        video_bit_rate = std::stoi(sanitize_bitrate(line.substr(line.find('=') + 1)));
		    }
		    catch (const std::invalid_argument& e)
		    {
		        video_bit_rate = 0;
		    }
		}
		else if (line.find("width=") != std::string::npos)
		{
		    width = std::stoi(line.substr(line.find('=') + 1));
		}
		else if (line.find("height=") != std::string::npos)
		{
		    height = std::stoi(line.substr(line.find('=') + 1));
		}
		else if (line.find("display_aspect_ratio=") != std::string::npos)
		{
		    sscanf(line.c_str(), "display_aspect_ratio=%d:%d", &aspect.first, &aspect.second);
		}
	} // Здесь должна быть закрывающая фигурная скобка

    else if (codec_type == "audio")
    {
        if (line.find("bit_rate=") != std::string::npos)
        {
            try
            {
                //audio_bit_rate = std::stoi(line.substr(line.find('=') + 1));
				audio_bit_rate = std::stoi(sanitize_bitrate(line.substr(line.find('=') + 1)));
            }
            catch (const std::invalid_argument& e)
            {
                audio_bit_rate = 0;
            }
        }
    }

}
	
	
    resolution = std::make_pair(width, height);
    int total_bit_rate = video_bit_rate + audio_bit_rate;

    return std::make_tuple(total_bit_rate, resolution, aspect);
}


void convert_video(const std::string& input_path)
{       
    int bit_rate;
    std::pair<int, int> resolution, aspect;
    std::tie(bit_rate, resolution, aspect) = get_video_info(input_path);
    std::cout << "Bitrate: " << bit_rate << " Resolution: " << resolution.first << "x" << resolution.second << " Aspect Ratio: " << aspect.first << ":" << aspect.second << std::endl;

    const auto last_dot_index = input_path.find_last_of('.');
    std::string output_path = input_path.substr(0, last_dot_index) + ".mp4";

    std::string command = "ffmpeg -i \"" + input_path + "\" -c:v libx264 -c:a aac \"" + output_path + "\"";
    //std::string command = "ffprobe -i \"" + input_path; // + "\" -c:v libx264 -c:a aac \"" + output_path + "\"";

	std::cout << command << std::endl;
	
    system(command.c_str());
}

void traverse_directory()
{
    DIR* dir;
    dirent* entry;
    const std::string current_directory = ".";

    if ((dir = opendir(current_directory.c_str())) != nullptr)
    {
        while ((entry = readdir(dir)) != nullptr)
        {
            const std::string entry_name = entry->d_name;
            const auto ext_start = entry_name.find_last_of('.');

            if (ext_start != std::string::npos)
            {
                const std::string ext = entry_name.substr(ext_start);
                if (std::find(valid_extensions.begin(), valid_extensions.end(), ext) != valid_extensions.end())
                {
                    std::cout << "Converting video file: " << entry_name << std::endl;
                    convert_video(entry_name);
                }
            }
        }
        closedir(dir);
    }
}

int main()
{
    traverse_directory();
    return 0;
}

ya
^-^
Сообщения: 2336
Зарегистрирован: 16 дек 2021, 19:56

Re: ffmpeg переобожмёт во всех подкаталогах

Сообщение ya »

Переобожмёт все видеофайлы в формат mp4 (видеокодеком h.264 и аудиокодеком aac) из форматов {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v", ".VOB"} в каталоге и подкаталогах, начиная с каталога в котором размещена скомпилированная программа, затем удалит исходные видеофайлы

encdel2.cpp

Код: Выделить всё


#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <cmath>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <array> 
#include <sstream>
#include <algorithm>
#include <sys/stat.h>

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif


struct VideoInfo
{
    double total_duration;
    unsigned long int total_size;
    int total_bit_rate;
    std::pair<int, int> resolution;
    std::string aspect_ratio;
};

bool isValidNumber(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(),
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

bool file_exists(const std::string& filepath) {
    struct stat buffer;
    return (stat(filepath.c_str(), &buffer) == 0);
}

#ifdef _WIN32
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = _popen(cmd.c_str(), "rb");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = _pclose(fp);
        
        if (exit_code == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(exit_code));
        }
    }
#else
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = popen(cmd.c_str(), "r");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = pclose(fp);
        
        if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(WEXITSTATUS(exit_code)));
        }
    }
#endif

std::string get_aspect_ratio(const double aspect_ratio)
{
    int approx_ratio = static_cast<int>(std::round(aspect_ratio));
    switch (approx_ratio)
    {
        case 1:
            return "1:1";
        case 4:
            return "4:3";
        case 5:
            return "5:4";
        case 16:
            return "16:9";
        case 17:
            return "17:10";
        case 21:
            return "21:9";
        default:
            return std::to_string(approx_ratio);
    }
}

VideoInfo get_video_info(const std::string& input)
{
    std::string command = "ffprobe -v error -show_entries format=size,duration,bit_rate:stream=codec_type,width,height,bit_rate,display_aspect_ratio -of default=noprint_wrappers=1 -i \"" + input + "\"";
    std::istringstream ffprobe_pipe(run_command(command));
    
    std::unordered_map<std::string, std::string> info_map;
    std::string line;
    while (std::getline(ffprobe_pipe, line))
    {
        size_t pos = line.find('=');
        if (pos != std::string::npos)
        {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);

            if (value != "N/A")
            {
                info_map[key] = value;
            }
        }
    }

    VideoInfo info;
    info.total_duration = std::stod(info_map["duration"]);
	/*if (isValidNumber(info_map["size"]))
	{
		long double result;// = std::stoi(info_map["size"]);
    // ... используйте результат, если строки валидны
	}
	else
	{
    // обработка ошибки: ваша строка не является корректным числом
		throw std::invalid_argument("Invalid argument: size " + info_map["size"]);
	}*/
    //info.total_size = std::stoi(info_map["size"]);
    info.total_bit_rate = std::stoi(info_map["bit_rate"]);
    info.resolution = std::make_pair(std::stoi(info_map["width"]), std::stoi(info_map["height"]));
    double dar = std::stod(info_map["display_aspect_ratio"]);
    info.aspect_ratio = get_aspect_ratio(dar);
    
    return info;
}

std::string format_duration(double duration) 
{
    int hours = static_cast<int>(duration / 3600);
    duration -= hours * 3600;
    int minutes = static_cast<int>(duration / 60);
    duration -= minutes * 60;
    int seconds = static_cast<int>(duration);

    std::ostringstream formatted_duration;
    formatted_duration << std::setfill('0') << std::setw(2) << hours << ":"
                       << std::setw(2) << minutes << ":"
                       << std::setw(2) << seconds;

    return formatted_duration.str();
}

void set_input_file(const std::string& input_path)
{
    VideoInfo video_info = get_video_info(input_path);
	
	std::string formatted_duration = format_duration(video_info.total_duration);

    std::cout << "Duration: " << formatted_duration << " " << std::endl;
    //std::cout << "Size: " << video_info.total_size << " byte" << std::endl;
    std::cout << "Total bitrate: " << (ceil(video_info.total_bit_rate/(1000*100))/10) << " Mbps" << std::endl;
    std::cout << "Resolution: " << video_info.resolution.first << "x" << video_info.resolution.second << std::endl;
    std::cout << "Aspect ratio: " << video_info.aspect_ratio << std::endl;

}



/*
if (isValidNumber(your_string))
{
    int result = std::stoi(your_string);
    // ... используйте результат, если строки валидны
}
else
{
    // обработка ошибки: ваша строка не является корректным числом
    throw std::invalid_argument("Invalid argument: " + your_string);
}
*/



std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v", ".VOB"};


std::string format_ffmpeg(const std::string& input_path)
{
	VideoInfo video_info = get_video_info(input_path);
	std::ostringstream formatted_ffmpeg;
   
	if((video_info.resolution.second >= 1080) && (video_info.resolution.first > 1280))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if(((ceil(video_info.total_bit_rate/(1000*100))/10) > 8.1) || ((ceil(video_info.total_bit_rate/(1000*100))/10) < 5))
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "8M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1920x1080"; 
	}
	else if ((video_info.resolution.first == 1280)&& (video_info.resolution.second == 720))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if((ceil(video_info.total_bit_rate/(1000*100))/10) > 5.3)
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "5M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1280x720"; 
		
	}
	else
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v 4.5M -vf yadif -preset slow "; 
	}
	
    //formatted_ffmpeg << std::setfill('0') << std::setw(2) << s;

    return formatted_ffmpeg.str();
}


std::string slash_replace(const std::string& input_path)
{
	std::string path = input_path;
    std::cout << "Original path: " << path << std::endl;
    
    // Find and replace all slashes with backslashes
    size_t pos = 0;
    while ((pos = path.find('/', pos)) != std::string::npos) {
        path.replace(pos, 1, "\\");
        pos += 1;
    }
    
    std::cout << "Updated path: " << path << std::endl;
    
    return path;
}

void convert_video(const std::string& input_path)
{
    const auto last_dot_index = input_path.find_last_of('.');
    std::string output_path = input_path.substr(0, last_dot_index) + ".mp4";
	
	std::string command = "ffmpeg -i \"" + input_path; 
	command += "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -c:v libx264 ";
	command += format_ffmpeg(input_path) + " -r 29.97 -c:a ";
//#ifdef _WIN32
//	command += "libvo_aacenc";
//#else
	command += "aac";
//#endif
	command += " -b:a 320K -n \""+ output_path + "\"";
    std::cout << "command: " << command << std::endl;
	std::cout << std::endl;
	
	system(command.c_str());

	// Удалит входной файл после обработки
	std::string command_rm_input_path = "";
#ifdef _WIN32
    system("timeout /t 2");
	command_rm_input_path = "DEL /Q /F \"" + slash_replace(input_path) +"\"";
#else
    system("sleep 2");
	command_rm_input_path = "rm -y \"" + input_path + "\"";
#endif
	system(command_rm_input_path.c_str());
}

// Включайте все заголовки, как указано в вашем исходном коде

// Используйте функции: run_command, get_aspect_ratio, get_video_info,
// set_input_file, format_duration, format_ffmpeg, convert_video, как и в вашем исходном коде


bool is_directory(const std::string& directory_path, dirent* entry)
{
#ifdef _DIRENT_HAVE_D_TYPE
    return entry->d_type == DT_DIR;
#else
    struct stat path_stat;
    std::string full_path = directory_path + "/" + entry->d_name;
    if (stat(full_path.c_str(), &path_stat) == 0)
    {
        return S_ISDIR(path_stat.st_mode);
    }
    else
    {
        return false;
    }
#endif
}


void traverse_directory(const std::string& directory_path)
{
    DIR* dir;
    dirent* entry;

    if ((dir = opendir(directory_path.c_str())) != nullptr)
    {
        while ((entry = readdir(dir)) != nullptr)
        {
            if (is_directory(directory_path, entry))
            {
                std::string sub_directory = entry->d_name;

                if (sub_directory != "." && sub_directory != "..")
                {
                    traverse_directory(directory_path + "/" + sub_directory);
                }
            }
            else
            {
                const std::string entry_name = entry->d_name;
                const auto ext_start = entry_name.find_last_of('.');

                if (ext_start != std::string::npos)
                {
                    const std::string ext = entry_name.substr(ext_start);

                    if (std::find(valid_extensions.begin(), valid_extensions.end(), std::string(ext)) != valid_extensions.end())
                    {
                        std::string file_path = directory_path + "/" + entry_name;

                        std::cout << "Converting video file: " << file_path << std::endl;
                        set_input_file(file_path);
                        convert_video(file_path);
                    }
                }
            }
        }
        closedir(dir);
    }
}


int main()
{
    std::string start_directory = ".";  // Задайте стартовый каталог (или измените на нужный)
    traverse_directory(start_directory);

    return 0;
}

ya
^-^
Сообщения: 2336
Зарегистрирован: 16 дек 2021, 19:56

Re: ffmpeg переобожмёт во всех подкаталогах

Сообщение ya »

Добавлено: в качестве необязательного входного параметра можно указать каталог с какого пережимать видеофайлы

encdel4.cpp

Код: Выделить всё


#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <cmath>
#include <filesystem>
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <array> 
#include <sstream>
#include <algorithm>
#include <sys/stat.h>
#include <cstring> // для strerror

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif


struct VideoInfo
{
    double total_duration;
    unsigned long int total_size;
    int total_bit_rate;
    std::pair<int, int> resolution;
    std::string aspect_ratio;
};

bool isValidNumber(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(),
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

bool file_exists(const std::string& filepath) {
    struct stat buffer;
    return (stat(filepath.c_str(), &buffer) == 0);
}

#ifdef _WIN32
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = _popen(cmd.c_str(), "rb");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = _pclose(fp);
        
        if (exit_code == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(exit_code));
        }
    }
#else
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = popen(cmd.c_str(), "r");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = pclose(fp);
        
        if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(WEXITSTATUS(exit_code)));
        }
    }
#endif

std::string get_aspect_ratio(const double aspect_ratio)
{
    int approx_ratio = static_cast<int>(std::round(aspect_ratio));
    switch (approx_ratio)
    {
        case 1:
            return "1:1";
        case 4:
            return "4:3";
        case 5:
            return "5:4";
        case 16:
            return "16:9";
        case 17:
            return "17:10";
        case 21:
            return "21:9";
        default:
            return std::to_string(approx_ratio);
    }
}

#include <stdexcept> // Убедитесь, что этот заголовок подключен

VideoInfo get_video_info(const std::string& input)
{
    std::string command = "ffprobe -v error -show_entries format=size,duration,bit_rate:stream=codec_type,width,height,bit_rate,display_aspect_ratio -of default=noprint_wrappers=1 -i \"" + input + "\"";
    std::istringstream ffprobe_pipe(run_command(command));
    
    std::unordered_map<std::string, std::string> info_map;
    std::string line;
    while (std::getline(ffprobe_pipe, line))
    {
        size_t pos = line.find('=');
        if (pos != std::string::npos)
        {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);

            if (value != "N/A")
            {
                info_map[key] = value;
            }
        }
    }

    // Отладочная информация
    std::cout << "Extracted video info:" << std::endl;
    for (const auto& entry : info_map) {
        std::cout << entry.first << ": " << entry.second << std::endl;
    }

    VideoInfo info;

    try {
        info.total_duration = std::stod(info_map.at("duration"));
    } catch (const std::exception& e) {
        throw std::invalid_argument("Invalid argument for duration: " + info_map["duration"]);
    }

    try {
        info.total_size = std::stoul(info_map.at("size"));
    } catch (const std::exception& e) {
        info.total_size = 0; // Или выбросьте исключение, если size критичен
    }

    try {
        info.total_bit_rate = std::stoi(info_map.at("bit_rate"));
    } catch (const std::exception& e) {
        throw std::invalid_argument("Invalid argument for bit rate: " + info_map["bit_rate"]);
    }

    try {
        info.resolution = std::make_pair(std::stoi(info_map.at("width")), std::stoi(info_map.at("height")));
    } catch (const std::exception& e) {
        throw std::invalid_argument("Invalid arguments for resolution: " + info_map["width"] + ", " + info_map["height"]);
    }

    // Проверка наличия display_aspect_ratio
    if (info_map.find("display_aspect_ratio") != info_map.end()) 
	{
		double dar = std::stod(info_map.at("display_aspect_ratio"));
		info.aspect_ratio = get_aspect_ratio(dar);
    } 
	else 
	{
         info.aspect_ratio = {0, 0}; // Присвоить значение по умолчанию, если не указано
    }
	
    return info;
}

std::string format_duration(double duration) 
{
    int hours = static_cast<int>(duration / 3600);
    duration -= hours * 3600;
    int minutes = static_cast<int>(duration / 60);
    duration -= minutes * 60;
    int seconds = static_cast<int>(duration);

    std::ostringstream formatted_duration;
    formatted_duration << std::setfill('0') << std::setw(2) << hours << ":"
                       << std::setw(2) << minutes << ":"
                       << std::setw(2) << seconds;

    return formatted_duration.str();
}

void set_input_file(const std::string& input_path)
{
    VideoInfo video_info = get_video_info(input_path);
	
	std::string formatted_duration = format_duration(video_info.total_duration);

    std::cout << "Duration: " << formatted_duration << " " << std::endl;
    //std::cout << "Size: " << video_info.total_size << " byte" << std::endl;
    std::cout << "Total bitrate: " << (ceil(video_info.total_bit_rate/(1000*100))/10) << " Mbps" << std::endl;
    std::cout << "Resolution: " << video_info.resolution.first << "x" << video_info.resolution.second << std::endl;
    std::cout << "Aspect ratio: " << video_info.aspect_ratio << std::endl;

}



/*
if (isValidNumber(your_string))
{
    int result = std::stoi(your_string);
    // ... используйте результат, если строки валидны
}
else
{
    // обработка ошибки: ваша строка не является корректным числом
    throw std::invalid_argument("Invalid argument: " + your_string);
}
*/



std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v", ".VOB"};


std::string format_ffmpeg(const std::string& input_path)
{
	VideoInfo video_info = get_video_info(input_path);
	std::ostringstream formatted_ffmpeg;
   
	if((video_info.resolution.second >= 1080) && (video_info.resolution.first > 1280))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if(((ceil(video_info.total_bit_rate/(1000*100))/10) > 8.1) || ((ceil(video_info.total_bit_rate/(1000*100))/10) < 5))
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "8M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1920x1080"; 
	}
	else if ((video_info.resolution.first == 1280)&& (video_info.resolution.second == 720))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if((ceil(video_info.total_bit_rate/(1000*100))/10) > 5.3)
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "5M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1280x720"; 
		
	}
	else
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v 4.5M -vf yadif -preset slow "; 
	}
	
    //formatted_ffmpeg << std::setfill('0') << std::setw(2) << s;

    return formatted_ffmpeg.str();
}


std::string slash_replace(const std::string& input_path)
{
	std::string path = input_path;
    std::cout << "Original path: " << path << std::endl;
    
    // Find and replace all slashes with backslashes
    size_t pos = 0;
    while ((pos = path.find('/', pos)) != std::string::npos) {
        path.replace(pos, 1, "\\");
        pos += 1;
    }
    
    std::cout << "Updated path: " << path << std::endl;
    
    return path;
}

void convert_video(const std::string& input_path)
{
    const auto last_dot_index = input_path.find_last_of('.');
    std::string output_path = input_path.substr(0, last_dot_index) + ".mp4";
	
	std::string command = "ffmpeg -i \"" + input_path; 
	command += "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -c:v libx264 ";
	command += format_ffmpeg(input_path) + " -r 29.97 -c:a ";
//#ifdef _WIN32
//	command += "libvo_aacenc";
//#else
	command += "aac";
//#endif
	command += " -b:a 320K -n \""+ output_path + "\"";
    std::cout << "command: " << command << std::endl;
	std::cout << std::endl;
	
	system(command.c_str());

	// Удалит входной файл после обработки
	std::string command_rm_input_path = "";
#ifdef _WIN32
    system("timeout /t 2");
	command_rm_input_path = "DEL /Q /F \"" + slash_replace(input_path) +"\"";
#else
    system("sleep 2");
	command_rm_input_path = "rm -y \"" + input_path + "\"";
#endif
	system(command_rm_input_path.c_str());
}

// Включайте все заголовки, как указано в вашем исходном коде

// Используйте функции: run_command, get_aspect_ratio, get_video_info,
// set_input_file, format_duration, format_ffmpeg, convert_video, как и в вашем исходном коде

bool is_directory([[maybe_unused]] const std::string& directory_path, dirent* entry)
{
#ifdef _DIRENT_HAVE_D_TYPE
    return entry->d_type == DT_DIR;
#else
    struct stat path_stat;
    std::string full_path = directory_path + "/" + entry->d_name;
    if (stat(full_path.c_str(), &path_stat) == 0)
    {
        return S_ISDIR(path_stat.st_mode);
    }
    else
    {
        return false;
    }
#endif
}


void traverse_directory(const std::string& directory_path)
{
    DIR* dir;
    dirent* entry;

    if ((dir = opendir(directory_path.c_str())) != nullptr)
    {
        while ((entry = readdir(dir)) != nullptr)
        {
            if (is_directory(directory_path, entry))
            {
                std::string sub_directory = entry->d_name;

                if (sub_directory != "." && sub_directory != "..")
                {
                    traverse_directory(directory_path + "/" + sub_directory);
                }
            }
            else
            {
                const std::string entry_name = entry->d_name;
                const auto ext_start = entry_name.find_last_of('.');

                if (ext_start != std::string::npos)
                {
                    const std::string ext = entry_name.substr(ext_start);

                    if (std::find(valid_extensions.begin(), valid_extensions.end(), std::string(ext)) != valid_extensions.end())
                    {
                        std::string file_path = directory_path + "/" + entry_name;

                        std::cout << "Converting video file: " << file_path << std::endl;
                        set_input_file(file_path);
                        convert_video(file_path);
                    }
                }
            }
        }
        closedir(dir);
    }
}

int main(int argc, char* argv[])
{
    std::string start_directory = ".";  // Значение по умолчанию - текущий каталог

    if (argc > 1) 
	{
        start_directory = argv[1];  // Если передан первый аргумент, используется он
    }

    traverse_directory(start_directory);

    return 0;
}

/*
int main()
{
    std::string start_directory = ".";  // Задайте стартовый каталог (или измените на нужный)
    traverse_directory(start_directory);

    return 0;
}
*/

Makefile

Код: Выделить всё

# Определяем компилятор и флаги компиляции
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra

# Основной целевой файл
TARGET = encode

# Исходные файлы
SRCS = encdel4.cpp  # Замените 'main.cpp' на имя вашего файла с кодом

# Объектные файлы
OBJS = $(SRCS:.cpp=.o)

# Правило по умолчанию для сборки
all: $(TARGET)

# Линковка объекта в исполняемый файл
$(TARGET): $(OBJS)
	$(CXX) $(OBJS) -o $(TARGET)

# Правило для компиляции исходников в объектные файлы
%.o: %.cpp
	$(CXX) $(CXXFLAGS) -c $< -o $@

# Правило для очистки
clean:
	rm -f $(OBJS) $(TARGET)

.PHONY: all clean

Вложения
encode4.zip
откомпилированное под winду
(705.05 КБ) 26 скачиваний
encode4.zip
откомпилированное под winду
(705.05 КБ) 26 скачиваний
ya
^-^
Сообщения: 2336
Зарегистрирован: 16 дек 2021, 19:56

Re: ffmpeg переобожмёт во всех подкаталогах

Сообщение ya »

encdel4.cpp

Код: Выделить всё

#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <dirent.h>
#include <algorithm>
#include <iomanip>
#include <iostream>
#include <string>
#include <cmath>
#ifdef _WIN32
#include <filesystem>
#else
#include <experimental/filesystem>
#endif
#include <fstream>
#include <iterator>
#include <stdexcept>
#include <unordered_map>
#include <utility>
#include <array> 
#include <sstream>
#include <algorithm>
#include <sys/stat.h>
#include <cstring> // для strerror

#ifdef _WIN32
    #include <windows.h>
#else
    #include <unistd.h>
#endif


struct VideoInfo
{
    double total_duration;
    unsigned long int total_size;
    int total_bit_rate;
    std::pair<int, int> resolution;
    std::string aspect_ratio;
};

bool isValidNumber(const std::string& s)
{
    return !s.empty() && std::find_if(s.begin(),
        s.end(), [](unsigned char c) { return !std::isdigit(c); }) == s.end();
}

bool file_exists(const std::string& filepath) {
    struct stat buffer;
    return (stat(filepath.c_str(), &buffer) == 0);
}

#ifdef _WIN32
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = _popen(cmd.c_str(), "rb");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = _pclose(fp);
        
        if (exit_code == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(exit_code));
        }
    }
#else
    std::string run_command(const std::string& command)
    {
        std::string cmd = command + " 2>&1";
        FILE* fp = popen(cmd.c_str(), "r");
        if (fp == nullptr)
        {
            throw std::runtime_error("popen error: " + std::string(strerror(errno)));
        }
        
        std::array<char, 256> buffer;
        
        std::string result;
        while (fgets(buffer.data(), 256, fp) != nullptr)
        {
            result += buffer.data();
        }
    
        int exit_code = pclose(fp);
        
        if (WIFEXITED(exit_code) && WEXITSTATUS(exit_code) == 0)
        {
            return result;
        }
        else
        {
            throw std::runtime_error("Command error: exit code = " + std::to_string(WEXITSTATUS(exit_code)));
        }
    }
#endif

std::string get_aspect_ratio(const double aspect_ratio)
{
    int approx_ratio = static_cast<int>(std::round(aspect_ratio));
    switch (approx_ratio)
    {
        case 1:
            return "1:1";
        case 4:
            return "4:3";
        case 5:
            return "5:4";
        case 16:
            return "16:9";
        case 17:
            return "17:10";
        case 21:
            return "21:9";
        default:
            return std::to_string(approx_ratio);
    }
}

#include <stdexcept> // Убедитесь, что этот заголовок подключен

VideoInfo get_video_info(const std::string& input)
{
    std::string command = "ffprobe -v error -show_entries format=size,duration,bit_rate:stream=codec_type,width,height,bit_rate,display_aspect_ratio -of default=noprint_wrappers=1 -i \"" + input + "\"";
    std::istringstream ffprobe_pipe(run_command(command));
    
    std::unordered_map<std::string, std::string> info_map;
    std::string line;
    while (std::getline(ffprobe_pipe, line))
    {
        size_t pos = line.find('=');
        if (pos != std::string::npos)
        {
            std::string key = line.substr(0, pos);
            std::string value = line.substr(pos + 1);

            if (value != "N/A")
            {
                info_map[key] = value;
            }
        }
    }

    // Отладочная информация
    std::cout << "Extracted video info:" << std::endl;
    for (const auto& entry : info_map) {
        std::cout << entry.first << ": " << entry.second << std::endl;
    }

    VideoInfo info;

    try {
        info.total_duration = std::stod(info_map.at("duration"));
    } catch (const std::exception& e) {
        throw std::invalid_argument("Invalid argument for duration: " + info_map["duration"]);
    }

    try {
        info.total_size = std::stoul(info_map.at("size"));
    } catch (const std::exception& e) {
        info.total_size = 0; // Или выбросьте исключение, если size критичен
    }

    try {
        info.total_bit_rate = std::stoi(info_map.at("bit_rate"));
    } catch (const std::exception& e) {
        throw std::invalid_argument("Invalid argument for bit rate: " + info_map["bit_rate"]);
    }

    try {
        info.resolution = std::make_pair(std::stoi(info_map.at("width")), std::stoi(info_map.at("height")));
    } catch (const std::exception& e) {
        throw std::invalid_argument("Invalid arguments for resolution: " + info_map["width"] + ", " + info_map["height"]);
    }

    // Проверка наличия display_aspect_ratio
    if (info_map.find("display_aspect_ratio") != info_map.end()) 
	{
		double dar = std::stod(info_map.at("display_aspect_ratio"));
		info.aspect_ratio = get_aspect_ratio(dar);
    } 
	else 
	{
         info.aspect_ratio = {0, 0}; // Присвоить значение по умолчанию, если не указано
    }
	
    return info;
}

std::string format_duration(double duration) 
{
    int hours = static_cast<int>(duration / 3600);
    duration -= hours * 3600;
    int minutes = static_cast<int>(duration / 60);
    duration -= minutes * 60;
    int seconds = static_cast<int>(duration);

    std::ostringstream formatted_duration;
    formatted_duration << std::setfill('0') << std::setw(2) << hours << ":"
                       << std::setw(2) << minutes << ":"
                       << std::setw(2) << seconds;

    return formatted_duration.str();
}

void set_input_file(const std::string& input_path)
{
    VideoInfo video_info = get_video_info(input_path);
	
	std::string formatted_duration = format_duration(video_info.total_duration);

    std::cout << "Duration: " << formatted_duration << " " << std::endl;
    //std::cout << "Size: " << video_info.total_size << " byte" << std::endl;
    std::cout << "Total bitrate: " << (ceil(video_info.total_bit_rate/(1000*100))/10) << " Mbps" << std::endl;
    std::cout << "Resolution: " << video_info.resolution.first << "x" << video_info.resolution.second << std::endl;
    std::cout << "Aspect ratio: " << video_info.aspect_ratio << std::endl;

}



/*
if (isValidNumber(your_string))
{
    int result = std::stoi(your_string);
    // ... используйте результат, если строки валидны
}
else
{
    // обработка ошибки: ваша строка не является корректным числом
    throw std::invalid_argument("Invalid argument: " + your_string);
}
*/



std::vector<std::string> valid_extensions = {".wmv", ".avi", ".asf", ".flv", ".mkv", ".m4v", ".VOB"};


std::string format_ffmpeg(const std::string& input_path)
{
	VideoInfo video_info = get_video_info(input_path);
	std::ostringstream formatted_ffmpeg;
   
	if((video_info.resolution.second >= 1080) && (video_info.resolution.first > 1280))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if(((ceil(video_info.total_bit_rate/(1000*100))/10) > 8.1) || ((ceil(video_info.total_bit_rate/(1000*100))/10) < 5))
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "8M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1920x1080"; 
	}
	else if ((video_info.resolution.first == 1280)&& (video_info.resolution.second == 720))
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v "; 
		if((ceil(video_info.total_bit_rate/(1000*100))/10) > 5.3)
		{
			 formatted_ffmpeg << std::setfill('0') << std::setw(1) << "5M ";		
		}
		else
		{
			formatted_ffmpeg << std::setfill('0') << std::setw(2) << (ceil(video_info.total_bit_rate/(1000*100))/10) << "M ";
		}
		formatted_ffmpeg << std::setfill('0') << std::setw(1) <<  " -s 1280x720"; 
		
	}
	else
	{
		formatted_ffmpeg << std::setfill('0') << std::setw(1) << " -b:v 4.5M -vf yadif -preset slow "; 
	}
	
    //formatted_ffmpeg << std::setfill('0') << std::setw(2) << s;

    return formatted_ffmpeg.str();
}


std::string slash_replace(const std::string& input_path)
{
	std::string path = input_path;
    std::cout << "Original path: " << path << std::endl;
    
    // Find and replace all slashes with backslashes
    size_t pos = 0;
    while ((pos = path.find('/', pos)) != std::string::npos) {
        path.replace(pos, 1, "\\");
        pos += 1;
    }
    
    std::cout << "Updated path: " << path << std::endl;
    
    return path;
}

void convert_video(const std::string& input_path)
{
    const auto last_dot_index = input_path.find_last_of('.');
    std::string output_path = input_path.substr(0, last_dot_index) + ".mp4";
	
	std::string command = "ffmpeg -i \"" + input_path; 
	command += "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -c:v libx264 ";
	command += format_ffmpeg(input_path) + " -r 29.97 -c:a ";
//#ifdef _WIN32
//	command += "libvo_aacenc";
//#else
	command += "aac";
//#endif
	command += " -b:a 320K -n \""+ output_path + "\"";
    std::cout << "command: " << command << std::endl;
	std::cout << std::endl;
	
	system(command.c_str());

	// Удалит входной файл после обработки
	std::string command_rm_input_path = "";
#ifdef _WIN32
    system("timeout /t 2");
	command_rm_input_path = "DEL /Q /F \"" + slash_replace(input_path) +"\"";
#else
    system("sleep 2");
	command_rm_input_path = "rm -y \"" + input_path + "\"";
#endif
	system(command_rm_input_path.c_str());
}

// Включайте все заголовки, как указано в вашем исходном коде

// Используйте функции: run_command, get_aspect_ratio, get_video_info,
// set_input_file, format_duration, format_ffmpeg, convert_video, как и в вашем исходном коде

bool is_directory([[maybe_unused]] const std::string& directory_path, dirent* entry)
{
#ifdef _DIRENT_HAVE_D_TYPE
    return entry->d_type == DT_DIR;
#else
    struct stat path_stat;
    std::string full_path = directory_path + "/" + entry->d_name;
    if (stat(full_path.c_str(), &path_stat) == 0)
    {
        return S_ISDIR(path_stat.st_mode);
    }
    else
    {
        return false;
    }
#endif
}


void traverse_directory(const std::string& directory_path)
{
    DIR* dir;
    dirent* entry;

    if ((dir = opendir(directory_path.c_str())) != nullptr)
    {
        while ((entry = readdir(dir)) != nullptr)
        {
            if (is_directory(directory_path, entry))
            {
                std::string sub_directory = entry->d_name;

                if (sub_directory != "." && sub_directory != "..")
                {
                    traverse_directory(directory_path + "/" + sub_directory);
                }
            }
            else
            {
                const std::string entry_name = entry->d_name;
                const auto ext_start = entry_name.find_last_of('.');

                if (ext_start != std::string::npos)
                {
                    const std::string ext = entry_name.substr(ext_start);

                    if (std::find(valid_extensions.begin(), valid_extensions.end(), std::string(ext)) != valid_extensions.end())
                    {
                        std::string file_path = directory_path + "/" + entry_name;

                        std::cout << "Converting video file: " << file_path << std::endl;
                        set_input_file(file_path);
                        convert_video(file_path);
                    }
                }
            }
        }
        closedir(dir);
    }
}

int main(int argc, char* argv[])
{
    std::string start_directory = ".";  // Значение по умолчанию - текущий каталог

    if (argc > 1) 
	{
        start_directory = argv[1];  // Если передан первый аргумент, используется он
    }

    traverse_directory(start_directory);

    return 0;
}

/*
int main()
{
    std::string start_directory = ".";  // Задайте стартовый каталог (или измените на нужный)
    traverse_directory(start_directory);

    return 0;
}
*/
Makefile

Код: Выделить всё

# Определяем компилятор и флаги компиляции
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra

# Основной целевой файл
TARGET = encode

# Исходные файлы
SRCS = encdel4.cpp

# Объектные файлы
OBJS = $(SRCS:.cpp=.o)

# Правило по умолчанию для сборки
all: $(TARGET)

# Линковка объекта в исполняемый файл
$(TARGET): $(OBJS)
        $(CXX) $(OBJS) -o $(TARGET) -lstdc++fs

# Правило для компиляции исходников в объектные файлы
%.o: %.cpp
        $(CXX) $(CXXFLAGS) -c $< -o $@

# Правило для очистки
clean:
        rm -f $(OBJS) $(TARGET)

.PHONY: all clean
Ответить