Страница 1 из 1
Сохранить фрагмент из видеофайла (нарезка на фрагменты)
Добавлено: 23 мар 2025, 01:51
ya
Компиляция:
Использование:
где 0:0:59 - начало фрагмента, а 0:1:37 - конец фрагмента, причём конец фрагмента может отсутствовать
Re: Сохранить фрагмент из видеофайла (нарезка на фрагменты)
Добавлено: 23 мар 2025, 03:27
ya
добавлено: если ранее создан файл с метками времени, то не создавать его заново
splitter.cpp
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib> // Для system()
#include <algorithm>
#include <ctime> // Для работы с датой и временем
const std::string OUTPUT_SUFFIX = ".output.mp4"; // Суффикс для выходного файла
struct Time {
int hours, minutes;
double seconds;
Time(int h = 0, int m = 0, double s = 0.0) : hours(h), minutes(m), seconds(s) {}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool operator<(const Time& other) const {
if (hours != other.hours) return hours < other.hours;
if (minutes != other.minutes) return minutes < other.minutes;
return seconds < other.seconds;
}
bool operator>(const Time& other) const {
if (hours != other.hours) return hours > other.hours;
if (minutes != other.minutes) return minutes > other.minutes;
return seconds > other.seconds;
}
void subtract(double sec) {
seconds -= sec;
if (seconds < 0) {
seconds += 60;
minutes--;
}
if (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) {
hours = 0;
minutes = 0;
seconds = 0.0;
}
}
};
bool runFFProbe(const std::string& input_file, const std::string& output_file) {
std::string command = "ffprobe -i \"" + input_file + "\" -select_streams v -skip_frame nokey -show_frames -show_entries frame=pkt_pts_time -sexagesimal -print_format csv > \"" + output_file + "\"";
return system(command.c_str()) == 0; // Возвращает true, если команда выполнена успешно
}
bool checkIfFileExists(const std::string& filename) {
std::ifstream file(filename);
return file.good();
}
void formatTimestamps(const std::string& input_file, const std::string& output_file) {
std::ifstream infile(input_file);
std::ofstream outfile(output_file);
std::string line;
while (std::getline(infile, line)) {
size_t comma_pos = line.find(',');
if (comma_pos != std::string::npos) {
// Печатаем значение времени во втором столбце
outfile << line.substr(comma_pos + 1) << std::endl;
}
}
}
std::vector<Time> readKeyframesFromFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<Time> timestamps;
std::string line;
while (std::getline(file, line)) {
std::istringstream ss(line);
int h, m;
double s;
char colon1, colon2;
ss >> h >> colon1 >> m >> colon2 >> s;
if (ss && colon1 == ':' && colon2 == ':') {
timestamps.emplace_back(h, m, s);
}
}
return timestamps;
}
Time findMaxTimeLessThan(const std::string& filename, const Time& user_time) {
std::ifstream file(filename);
std::string line;
Time max_time(0, 0, 0.0);
while (std::getline(file, line)) {
std::istringstream ss(line);
int h, m;
double s;
char colon1, colon2;
ss >> h >> colon1 >> m >> colon2 >> s;
if (ss && colon1 == ':' && colon2 == ':') {
Time current_time(h, m, s);
if (current_time < user_time && current_time > max_time) {
max_time = current_time;
}
}
}
return max_time;
}
// Функция для получения текущей даты и времени в нужном формате
std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
// Функция для извлечения расширения файла
std::string getFileExtension(const std::string& filename) {
size_t dot_pos = filename.rfind('.');
if (dot_pos != std::string::npos) {
return filename.substr(dot_pos); // Возвращает все, что после последней точки
}
return ""; // Если точка не найдена, возвращаем пустую строку
}
int main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <input_file> <time_to_compare> <end_time (optional)>" << std::endl;
return 1;
}
std::string input_file = argv[1];
std::string search_time_str = argv[2];
std::string end_time_str = (argc > 3) ? argv[3] : ""; // Опциональный третий аргумент
// Генерация выходного файла ключевых кадров
std::string keyframe_file = input_file + "_keyframes.txt";
if (!checkIfFileExists(keyframe_file))
{
// Запуск ffprobe для извлечения ключевых кадров
if (!runFFProbe(input_file, keyframe_file)) {
std::cerr << "Error running ffprobe." << std::endl;
return 1;
}
// Создание файла с отформатированными временными метками
std::string formatted_keyframe_file = input_file + "_formatted_keyframes.txt";
formatTimestamps(keyframe_file, formatted_keyframe_file);
// Удаление оригинального файла с ключевыми кадрами
remove(keyframe_file.c_str());
// Переименование отформатированного файла
rename(formatted_keyframe_file.c_str(), keyframe_file.c_str());
}
// Разбор введенного времени пользователем
std::istringstream ss(search_time_str);
int h, m;
double s;
char colon1, colon2;
ss >> h >> colon1 >> m >> colon2 >> s;
Time user_time(h, m, s);
// Поиск наибольшего значения временной метки, меньшего чем user_time
Time max_time = findMaxTimeLessThan(keyframe_file, user_time);
// Вывод результата
if (max_time.seconds > 0) {
std::cout << "The largest time less than " << user_time.toString() << " is " << max_time.toString() << std::endl;
max_time.subtract(0.1); // Вычитаем 0.1 секунды
std::cout << "The time after subtracting 0:0:0.1 is " << max_time.toString() << std::endl;
// Формирование команды ffmpeg
// std::string current_datetime_suffix = getCurrentDateTimeString();
// std::string output_file = input_file + "." + current_datetime_suffix + ".mp4";
// Извлечение расширения входного файла
std::string file_extension = getFileExtension(input_file);
std::string current_datetime_suffix = getCurrentDateTimeString();
// Создание имени выходного файла с учетом расширения
std::string output_file = input_file.substr(0, input_file.size() - file_extension.size()) + "." + current_datetime_suffix + file_extension;
// Формирование команды ffmpeg
std::string command = "ffmpeg -i \"" + input_file + "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -ss " +
max_time.toString() + (end_time_str.empty() ? " " : (" -to " + end_time_str) ) +
" -c copy \"" + output_file + "\"";
// Выполнение команды ffmpeg
if (system(command.c_str()) != 0) {
std::cerr << "Error running ffmpeg." << std::endl;
return 1;
}
} else {
std::cout << "No time found less than " << user_time.toString() << "." << std::endl;
}
return 0;
}
Makefile
Код: Выделить всё
# Определяем компилятор и флаги компиляции
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra
# Основной целевой файл
TARGET = splitter
# Исходные файлы
SRCS = splitter.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
Re: Сохранить фрагмент из видеофайла (нарезка на фрагменты)
Добавлено: 23 мар 2025, 08:08
ya
Внесённые изменения: рефакторинг кода
splitter1.cpp
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib> // Для system()
#include <algorithm>
#include <ctime> // Для работы с датой и временем
class Time {
private:
int hours, minutes;
double seconds;
public:
Time(int h = 0, int m = 0, double s = 0.0) : hours(h), minutes(m), seconds(s) {}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool operator<(const Time& other) const {
return std::tie(hours, minutes, seconds) < std::tie(other.hours, other.minutes, other.seconds);
}
bool operator>(const Time& other) const {
return std::tie(hours, minutes, seconds) > std::tie(other.hours, other.minutes, other.seconds);
}
void subtract(double sec) {
seconds -= sec;
while (seconds < 0) {
seconds += 60;
minutes--;
}
while (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) {
hours = minutes = 0;
seconds = 0.0;
}
}
// Добавим метод для проверки валидности времени
bool isValid() const {
return (hours >= 0 && minutes >= 0 && seconds >= 0);
}
// Метод для доступа к полю seconds
double getSeconds() const {
return seconds;
}
};
class FrameExtractor {
public:
static bool runFFProbe(const std::string& input_file, const std::string& output_file) {
std::string command = "ffprobe -i \"" + input_file + "\" -select_streams v -skip_frame nokey -show_frames "
"-show_entries frame=pkt_pts_time -sexagesimal -print_format csv > \"" + output_file + "\"";
return system(command.c_str()) == 0; // Возвращает true, если команда выполнена успешно
}
static void formatTimestamps(const std::string& input_file, const std::string& output_file) {
std::ifstream infile(input_file);
std::ofstream outfile(output_file);
std::string line;
while (std::getline(infile, line)) {
size_t comma_pos = line.find(',');
if (comma_pos != std::string::npos) {
outfile << line.substr(comma_pos + 1) << std::endl; // Печатаем значение времени во втором столбце
}
}
}
};
class TimeUtils {
public:
static std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
static std::string getFileExtension(const std::string& filename) {
size_t dot_pos = filename.rfind('.');
return (dot_pos != std::string::npos) ? filename.substr(dot_pos) : ""; // Возвращает все, что после последней точки
}
};
class TimestampFileParser {
public:
static std::vector<Time> readKeyframesFromFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<Time> timestamps;
std::string line;
while (std::getline(file, line)) {
Time time = parseTime(line);
if (time.isValid()) {
timestamps.push_back(time);
}
}
return timestamps;
}
static Time findMaxTimeLessThan(const std::vector<Time>& timestamps, const Time& user_time) {
Time max_time;
for (const auto& current_time : timestamps) {
if (current_time < user_time && current_time > max_time) {
max_time = current_time;
}
}
return max_time;
}
private:
static Time parseTime(const std::string& time_string) {
int h, m;
double s;
char colon1, colon2;
std::istringstream ss(time_string);
ss >> h >> colon1 >> m >> colon2 >> s;
if (ss && colon1 == ':' && colon2 == ':') {
return Time(h, m, s);
}
return Time(); // Возвращаем время по умолчанию (0, 0, 0)
}
};
class Application {
private:
std::string input_file;
std::string keyframe_file;
public:
Application(const std::string& file) : input_file(file) {
keyframe_file = input_file + "_keyframes.txt";
}
void process(const std::string& search_time_str, const std::string& end_time_str) {
if (!checkIfFileExists(keyframe_file)) {
extractKeyframes();
}
Time user_time = parseSearchTime(search_time_str);
auto timestamps = TimestampFileParser::readKeyframesFromFile(keyframe_file);
Time max_time = TimestampFileParser::findMaxTimeLessThan(timestamps, user_time);
if (max_time.getSeconds() > 0) { // Используем метод getSeconds()
handleFoundTime(max_time, end_time_str);
} else {
std::cout << "No time found less than " << user_time.toString() << "." << std::endl;
}
}
private:
void extractKeyframes() {
std::string formatted_keyframe_file = input_file + "_formatted_keyframes.txt";
if (!FrameExtractor::runFFProbe(input_file, keyframe_file)) {
throw std::runtime_error("Error running ffprobe.");
}
FrameExtractor::formatTimestamps(keyframe_file, formatted_keyframe_file);
// Удаляем оригинальный файл с ключевыми кадрами
remove(keyframe_file.c_str());
// Переименовываем отформатированный файл
rename(formatted_keyframe_file.c_str(), keyframe_file.c_str());
}
Time parseSearchTime(const std::string& search_time_str) {
int h, m;
double s;
char colon1, colon2;
std::istringstream ss(search_time_str);
ss >> h >> colon1 >> m >> colon2 >> s;
return Time(h, m, s);
}
void handleFoundTime(Time& max_time, const std::string& end_time_str) {
max_time.subtract(0.1); // Вычитаем 0.1 секунды
std::string output_file = generateOutputFilename();
std::string command = buildFFmpegCommand(max_time, end_time_str, output_file);
if (system(command.c_str()) != 0) {
throw std::runtime_error("Error running ffmpeg.");
}
std::cout << "The largest time less than " << max_time.toString()
<< " is " << max_time.toString() << std::endl;
}
std::string generateOutputFilename() {
std::string file_extension = TimeUtils::getFileExtension(input_file);
std::string current_datetime_suffix = TimeUtils::getCurrentDateTimeString();
return input_file.substr(0, input_file.size() - file_extension.size())
+ "." + current_datetime_suffix + file_extension;
}
std::string buildFFmpegCommand(const Time& max_time, const std::string& end_time_str, const std::string& output_file) {
return "ffmpeg -i \"" + input_file + "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -ss "
+ max_time.toString() + (end_time_str.empty() ? "" : " -to " + end_time_str) + " -c copy \"" + output_file + "\"";
}
bool checkIfFileExists(const std::string& filename) {
std::ifstream file(filename);
return file.good();
}
};
int main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <input_file> <time_to_compare> <end_time (optional)>" << std::endl;
return 1;
}
try {
std::string input_file = argv[1];
std::string search_time_str = argv[2];
std::string end_time_str = (argc > 3) ? argv[3] : ""; // Опциональный третий аргумент
Application app(input_file);
app.process(search_time_str, end_time_str);
} catch (const std::runtime_error& e) {
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Re: Сохранить фрагмент из видеофайла (нарезка на фрагменты)
Добавлено: 30 мар 2025, 13:43
ya
исправлено: условие при котором время начала может быть равно 0
splitter3.cpp
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib> // Для system()
#include <algorithm>
#include <ctime> // Для работы с датой и временем
#include <tuple>
class Time {
private:
int hours, minutes;
double seconds;
public:
Time(int h = 0, int m = 0, double s = 0.0) : hours(h), minutes(m), seconds(s) {}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool operator<(const Time& other) const {
return std::tie(hours, minutes, seconds) < std::tie(other.hours, other.minutes, other.seconds);
}
bool operator>(const Time& other) const {
return std::tie(hours, minutes, seconds) > std::tie(other.hours, other.minutes, other.seconds);
}
void subtract(double sec) {
seconds -= sec;
while (seconds < 0) {
seconds += 60;
minutes--;
}
while (minutes < 0) {
minutes += 60;
hours--;
}
if (hours < 0) {
hours = minutes = 0;
seconds = 0.0;
}
}
// Добавим метод для проверки валидности времени
bool isValid() const {
return (hours >= 0 && minutes >= 0 && seconds >= 0);
}
// Метод для доступа к полю seconds
double getSeconds() const {
return seconds;
}
};
class FrameExtractor {
public:
static bool runFFProbe(const std::string& input_file, const std::string& output_file) {
std::string command = "ffprobe -i \"" + input_file + "\" -select_streams v -skip_frame nokey -show_frames "
"-show_entries frame=pkt_pts_time -sexagesimal -print_format csv > \"" + output_file + "\"";
return system(command.c_str()) == 0; // Возвращает true, если команда выполнена успешно
}
static void formatTimestamps(const std::string& input_file, const std::string& output_file) {
std::ifstream infile(input_file);
std::ofstream outfile(output_file);
std::string line;
while (std::getline(infile, line)) {
size_t comma_pos = line.find(',');
if (comma_pos != std::string::npos) {
outfile << line.substr(comma_pos + 1) << std::endl; // Печатаем значение времени во втором столбце
}
}
}
};
class TimeUtils {
public:
static std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
static std::string getFileExtension(const std::string& filename) {
size_t dot_pos = filename.rfind('.');
return (dot_pos != std::string::npos) ? filename.substr(dot_pos) : ""; // Возвращает все, что после последней точки
}
};
class TimestampFileParser {
public:
static std::vector<Time> readKeyframesFromFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<Time> timestamps;
std::string line;
while (std::getline(file, line)) {
Time time = parseTime(line);
if (time.isValid()) {
timestamps.push_back(time);
}
}
return timestamps;
}
static Time findMaxTimeLessThan(const std::vector<Time>& timestamps, const Time& user_time) {
Time max_time;
for (const auto& current_time : timestamps) {
if (current_time < user_time && current_time > max_time) {
max_time = current_time;
}
}
return max_time;
}
private:
static Time parseTime(const std::string& time_string) {
int h, m;
double s;
char colon1, colon2;
std::istringstream ss(time_string);
ss >> h >> colon1 >> m >> colon2 >> s;
if (ss && colon1 == ':' && colon2 == ':') {
return Time(h, m, s);
}
return Time(); // Возвращаем время по умолчанию (0, 0, 0)
}
};
class Application {
private:
std::string input_file;
std::string keyframe_file;
public:
Application(const std::string& file) : input_file(file) {
keyframe_file = input_file + "_keyframes.txt";
}
void process(const std::string& search_time_str, const std::string& end_time_str) {
if (search_time_str == "0") {
// Если second argument is "0", просто вызываем ffmpeg без дополнительных операций
generateAndRunFFmpegCommand(end_time_str);
return; // Возвращаемся, чтобы не производить дальнейшие операции
}
if (!checkIfFileExists(keyframe_file)) {
extractKeyframes();
}
Time user_time = parseSearchTime(search_time_str);
auto timestamps = TimestampFileParser::readKeyframesFromFile(keyframe_file);
Time max_time = TimestampFileParser::findMaxTimeLessThan(timestamps, user_time);
if (max_time.getSeconds() > 0) {
handleFoundTime(max_time, end_time_str);
} else {
std::cout << "No time found less than " << user_time.toString() << "." << std::endl;
}
}
private:
void extractKeyframes() {
std::string formatted_keyframe_file = input_file + "_formatted_keyframes.txt";
if (!FrameExtractor::runFFProbe(input_file, keyframe_file)) {
throw std::runtime_error("Error running ffprobe.");
}
FrameExtractor::formatTimestamps(keyframe_file, formatted_keyframe_file);
remove(keyframe_file.c_str());
rename(formatted_keyframe_file.c_str(), keyframe_file.c_str());
}
Time parseSearchTime(const std::string& search_time_str) {
int h, m;
double s;
char colon1, colon2;
std::istringstream ss(search_time_str);
ss >> h >> colon1 >> m >> colon2 >> s;
return Time(h, m, s);
}
void handleFoundTime(Time& max_time, const std::string& end_time_str) {
max_time.subtract(0.1);
std::string output_file = generateOutputFilename();
std::string command = buildFFmpegCommand(max_time, end_time_str, output_file);
if (system(command.c_str()) != 0) {
throw std::runtime_error("Error running ffmpeg.");
}
std::cout << "The largest time less than " << max_time.toString()
<< " is " << max_time.toString() << std::endl;
}
void generateAndRunFFmpegCommand(const std::string& end_time_str) {
std::string output_file = generateOutputFilename();
std::string command = "ffmpeg -i \"" + input_file + "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -c copy \"" + output_file + "\"";
if (!end_time_str.empty()) {
command.insert(command.find("-c copy") - 1, " -to " + end_time_str); // Добавление параметра -to
}
if (system(command.c_str()) != 0) {
throw std::runtime_error("Error running ffmpeg.");
}
std::cout << "Command executed successfully: " << command << std::endl;
}
std::string generateOutputFilename() {
std::string file_extension = TimeUtils::getFileExtension(input_file);
std::string current_datetime_suffix = TimeUtils::getCurrentDateTimeString();
return input_file.substr(0, input_file.size() - file_extension.size())
+ "." + current_datetime_suffix + file_extension;
}
std::string buildFFmpegCommand(const Time& max_time, const std::string& end_time_str, const std::string& output_file) {
return "ffmpeg -i \"" + input_file + "\" -map_metadata -1 -map_chapters -1 -avoid_negative_ts make_zero -ss "
+ max_time.toString() + (end_time_str.empty() ? "" : " -to " + end_time_str) + " -c copy \"" + output_file + "\"";
}
bool checkIfFileExists(const std::string& filename) {
std::ifstream file(filename);
return file.good();
}
};
int main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <input_file> <time_to_compare> <end_time (optional)>" << std::endl;
return 1;
}
try {
std::string input_file = argv[1];
std::string search_time_str = argv[2];
std::string end_time_str = (argc > 3) ? argv[3] : "";
Application app(input_file);
app.process(search_time_str, end_time_str);
} catch (const std::runtime_error& e) {
std::cerr << e.what() << std::endl;
return 1;
}
return 0;
}
Makefile
Код: Выделить всё
# Определяем компилятор и флаги компиляции
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra
# Основной целевой файл
TARGET = splitter
# Исходные файлы
SRCS = splitter3.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
Re: Сохранить фрагмент из видеофайла (нарезка на фрагменты)
Добавлено: 29 янв 2026, 03:48
ya
Необходимые пакеты для сборки
сборка:
Makefile
Код: Выделить всё
# Определяем компилятор и флаги компиляции
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra -ljson-c -I/usr/include/json-c
LDFLAGS = -L/usr/lib -ljson-c
# Основной целевой файл
TARGET = splitter
# Исходные файлы
SRCS = splitter3.cpp # Замените 'main.cpp' на имя вашего файла с кодом
# Объектные файлы
OBJS = $(SRCS:.cpp=.o)
# Правило по умолчанию для сборки
all: $(TARGET)
# Линковка объекта в исполняемый файл
$(TARGET): $(OBJS)
$(CXX) $(OBJS) -o $(TARGET)
# Правило для компиляции исходников в объектные файлы
%.o: %.cpp
$(CXX) $(CXXFLAGS) $(LDFLAGS) -c $< -o $@
# Правило для очистки
clean:
rm -f $(OBJS) $(TARGET)
.PHONY: all clean
Re: Сохранить фрагмент из видеофайла (нарезка на фрагменты)
Добавлено: 29 янв 2026, 04:59
ya
необходимые пакеты для сборки
Код: Выделить всё
sudo apt install make g++ pkg-config libjson-c-dev
замена пробелов на табуляторы в Makefile в начале каждой строки
Makefile
Код: Выделить всё
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra $(shell pkg-config --cflags json-c)
LDFLAGS = $(shell pkg-config --libs json-c)
TARGET = splitter
SRCS = splitter4.cpp
OBJS = $(SRCS:.cpp=.o)
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(OBJS) -o $(TARGET) $(LDFLAGS)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)
splitter4.cpp
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <tuple>
#include <json-c/json.h>
class Time {
private:
int hours, minutes;
double seconds;
public:
Time(int h = 0, int m = 0, double s = 0.0) : hours(h), minutes(m), seconds(s) {}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool operator<(const Time& other) const {
return std::tie(hours, minutes, seconds) < std::tie(other.hours, other.minutes, other.seconds);
}
bool operator>(const Time& other) const {
return std::tie(hours, minutes, seconds) > std::tie(other.hours, other.minutes, other.seconds);
}
void subtract(double sec) {
seconds -= sec;
while (seconds < 0) { seconds += 60; minutes--; }
while (minutes < 0) { minutes += 60; hours--; }
if (hours < 0) { hours = minutes = 0; seconds = 0.0; }
}
bool isValid() const { return (hours >= 0 && minutes >= 0 && seconds >= 0); }
double getSeconds() const { return seconds; }
double getTotalSeconds() const { return hours * 3600 + minutes * 60 + seconds; }
};
class FrameExtractor {
public:
static bool runFFProbe(const std::string& input_file, const std::string& output_json) {
// Запрашиваем только первый видеопоток и только ключевые кадры
std::string command = "ffprobe -v error -select_streams v:0 -skip_frame nokey "
"-show_entries frame=best_effort_timestamp_time "
"-of json \"" + input_file + "\" > \"" + output_json + "\"";
return system(command.c_str()) == 0;
}
static void formatTimestamps(const std::string& json_file, const std::string& txt_file) {
std::ifstream infile(json_file);
if (!infile.is_open()) return;
std::string content((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
infile.close();
struct json_object *parsed_json = json_tokener_parse(content.c_str());
struct json_object *frames;
if (parsed_json && json_object_object_get_ex(parsed_json, "frames", &frames)) {
std::ofstream outfile(txt_file);
size_t n_frames = json_object_array_length(frames);
for (size_t i = 0; i < n_frames; i++) {
struct json_object *frame = json_object_array_get_idx(frames, i);
struct json_object *ts_time;
if (json_object_object_get_ex(frame, "best_effort_timestamp_time", &ts_time)) {
outfile << json_object_get_string(ts_time) << std::endl;
}
}
}
if (parsed_json) json_object_put(parsed_json);
}
};
class TimeUtils {
public:
static std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
static std::string getFileExtension(const std::string& filename) {
size_t dot_pos = filename.rfind('.');
return (dot_pos != std::string::npos) ? filename.substr(dot_pos) : "";
}
};
class TimestampFileParser {
public:
static std::vector<Time> readKeyframesFromFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<Time> timestamps;
std::string line;
while (std::getline(file, line)) {
Time time = parseTime(line);
if (time.isValid()) timestamps.push_back(time);
}
return timestamps;
}
static Time findMaxTimeLessThan(const std::vector<Time>& timestamps, const Time& user_time) {
Time max_time(-1, -1, -1);
double user_total = user_time.getTotalSeconds();
for (const auto& current_time : timestamps) {
if (current_time.getTotalSeconds() < user_total) {
if (!max_time.isValid() || current_time.getTotalSeconds() > max_time.getTotalSeconds()) {
max_time = current_time;
}
}
}
return max_time;
}
static Time parseTime(const std::string& s) {
if (s.empty()) return Time(-1, -1, -1);
// Если это просто число (секунды)
if (s.find(':') == std::string::npos) {
try {
double ts = std::stod(s);
int h = (int)(ts / 3600);
int m = (int)((ts - h * 3600) / 60);
double sec = ts - h * 3600 - m * 60;
return Time(h, m, sec);
} catch (...) { return Time(-1, -1, -1); }
}
// Если это формат H:M:S
int h, m; double sec; char c1, c2;
std::istringstream ss(s);
if (ss >> h >> c1 >> m >> c2 >> sec) return Time(h, m, sec);
return Time(-1, -1, -1);
}
};
class Application {
private:
std::string input_file;
std::string keyframe_txt;
std::string keyframe_json;
public:
Application(const std::string& file) : input_file(file) {
keyframe_txt = input_file + "_keyframes.txt";
keyframe_json = input_file + "_keyframes.json";
}
void process(const std::string& search_time_str, const std::string& end_time_str) {
if (search_time_str == "0") {
generateAndRunFFmpegCommand(end_time_str);
return;
}
if (!checkIfFileExists(keyframe_txt)) {
extractKeyframes();
}
Time user_time = TimestampFileParser::parseTime(search_time_str);
auto timestamps = TimestampFileParser::readKeyframesFromFile(keyframe_txt);
Time max_time = TimestampFileParser::findMaxTimeLessThan(timestamps, user_time);
if (max_time.isValid()) {
handleFoundTime(max_time, end_time_str);
} else {
std::cout << "No keyframe found before " << user_time.toString() << ". Using start." << std::endl;
handleFoundTime(Time(0,0,0.1), end_time_str); // Подстраховка
}
}
private:
void extractKeyframes() {
std::cout << "Extracting keyframes to JSON..." << std::endl;
if (!FrameExtractor::runFFProbe(input_file, keyframe_json)) {
throw std::runtime_error("Error running ffprobe.");
}
std::cout << "Converting JSON to TXT..." << std::endl;
FrameExtractor::formatTimestamps(keyframe_json, keyframe_txt);
}
void handleFoundTime(Time max_time, const std::string& end_time_str) {
max_time.subtract(0.1); // Сдвиг для безопасной склейки
std::string output_file = generateOutputFilename();
std::string command = "ffmpeg -v error -ss " + max_time.toString() +
" -i \"" + input_file + "\" " +
(end_time_str.empty() ? "" : "-to " + end_time_str + " ") +
"-map_metadata -1 -c copy -avoid_negative_ts make_zero \"" + output_file + "\"";
std::cout << "Executing: " << command << std::endl;
if (system(command.c_str()) != 0) throw std::runtime_error("FFmpeg failed.");
std::cout << "Done! Saved as: " << output_file << std::endl;
}
void generateAndRunFFmpegCommand(const std::string& end_time_str) {
std::string output_file = generateOutputFilename();
std::string command = "ffmpeg -v error -i \"" + input_file + "\" -map_metadata -1 " +
(end_time_str.empty() ? "" : "-to " + end_time_str + " ") +
"-c copy \"" + output_file + "\"";
if (system(command.c_str()) != 0) throw std::runtime_error("FFmpeg failed.");
}
std::string generateOutputFilename() {
std::string ext = TimeUtils::getFileExtension(input_file);
return input_file.substr(0, input_file.size() - ext.size()) + "." + TimeUtils::getCurrentDateTimeString() + ext;
}
bool checkIfFileExists(const std::string& f) { std::ifstream file(f); return file.good(); }
};
int main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <input_file> <time_start> [time_end]" << std::endl;
return 1;
}
try {
Application app(argv[1]);
app.process(argv[2], (argc > 3 ? argv[3] : ""));
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
сборка
Re: Сохранить фрагмент из видеофайла (нарезка на фрагменты)
Добавлено: 29 янв 2026, 06:55
ya
splitter4.cpp
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <tuple>
#include <json-c/json.h>
class Time {
private:
int hours, minutes;
double seconds;
public:
Time(int h = 0, int m = 0, double s = 0.0) : hours(h), minutes(m), seconds(s) {}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool operator<(const Time& other) const {
return std::tie(hours, minutes, seconds) < std::tie(other.hours, other.minutes, other.seconds);
}
bool operator>(const Time& other) const {
return std::tie(hours, minutes, seconds) > std::tie(other.hours, other.minutes, other.seconds);
}
void subtract(double sec) {
seconds -= sec;
while (seconds < 0) { seconds += 60; minutes--; }
while (minutes < 0) { minutes += 60; hours--; }
if (hours < 0) { hours = minutes = 0; seconds = 0.0; }
}
bool isValid() const { return (hours >= 0 && minutes >= 0 && seconds >= 0); }
double getSeconds() const { return seconds; }
double getTotalSeconds() const { return hours * 3600 + minutes * 60 + seconds; }
};
class FrameExtractor {
public:
static bool runFFProbe(const std::string& input_file, const std::string& output_json) {
// Запрашиваем только первый видеопоток и только ключевые кадры
std::string command = "ffprobe -v error -select_streams v:0 -skip_frame nokey "
"-show_entries frame=best_effort_timestamp_time "
"-of json \"" + input_file + "\" > \"" + output_json + "\"";
return system(command.c_str()) == 0;
}
static void formatTimestamps(const std::string& json_file, const std::string& txt_file) {
std::ifstream infile(json_file);
if (!infile.is_open()) return;
std::string content((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
infile.close();
struct json_object *parsed_json = json_tokener_parse(content.c_str());
struct json_object *frames;
if (parsed_json && json_object_object_get_ex(parsed_json, "frames", &frames)) {
std::ofstream outfile(txt_file);
size_t n_frames = json_object_array_length(frames);
for (size_t i = 0; i < n_frames; i++) {
struct json_object *frame = json_object_array_get_idx(frames, i);
struct json_object *ts_time;
if (json_object_object_get_ex(frame, "best_effort_timestamp_time", &ts_time)) {
outfile << json_object_get_string(ts_time) << std::endl;
}
}
}
if (parsed_json) json_object_put(parsed_json);
}
};
class TimeUtils {
public:
static std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
static std::string getFileExtension(const std::string& filename) {
size_t dot_pos = filename.rfind('.');
return (dot_pos != std::string::npos) ? filename.substr(dot_pos) : "";
}
};
class TimestampFileParser {
public:
static std::vector<Time> readKeyframesFromFile(const std::string& filename) {
std::ifstream file(filename);
std::vector<Time> timestamps;
std::string line;
while (std::getline(file, line)) {
Time time = parseTime(line);
if (time.isValid()) timestamps.push_back(time);
}
return timestamps;
}
static Time findMaxTimeLessThan(const std::vector<Time>& timestamps, const Time& user_time) {
Time max_time(-1, -1, -1);
double user_total = user_time.getTotalSeconds();
for (const auto& current_time : timestamps) {
if (current_time.getTotalSeconds() < user_total) {
if (!max_time.isValid() || current_time.getTotalSeconds() > max_time.getTotalSeconds()) {
max_time = current_time;
}
}
}
return max_time;
}
static Time parseTime(const std::string& s) {
if (s.empty()) return Time(-1, -1, -1);
// Если это просто число (секунды)
if (s.find(':') == std::string::npos) {
try {
double ts = std::stod(s);
int h = (int)(ts / 3600);
int m = (int)((ts - h * 3600) / 60);
double sec = ts - h * 3600 - m * 60;
return Time(h, m, sec);
} catch (...) { return Time(-1, -1, -1); }
}
// Если это формат H:M:S
int h, m; double sec; char c1, c2;
std::istringstream ss(s);
if (ss >> h >> c1 >> m >> c2 >> sec) return Time(h, m, sec);
return Time(-1, -1, -1);
}
};
class Application {
private:
std::string input_file;
std::string keyframe_txt;
std::string keyframe_json;
public:
Application(const std::string& file) : input_file(file) {
keyframe_txt = input_file + "_keyframes.txt";
keyframe_json = input_file + "_keyframes.json";
}
void process(const std::string& search_time_str, const std::string& end_time_str) {
if (search_time_str == "0") {
generateAndRunFFmpegCommand(end_time_str);
return;
}
if (!checkIfFileExists(keyframe_txt)) {
extractKeyframes();
}
Time user_time = TimestampFileParser::parseTime(search_time_str);
auto timestamps = TimestampFileParser::readKeyframesFromFile(keyframe_txt);
Time max_time = TimestampFileParser::findMaxTimeLessThan(timestamps, user_time);
if (max_time.isValid()) {
handleFoundTime(max_time, end_time_str);
} else {
std::cout << "No keyframe found before " << user_time.toString() << ". Using start." << std::endl;
handleFoundTime(Time(0,0,0.1), end_time_str); // Подстраховка
}
}
private:
void extractKeyframes() {
std::cout << "Extracting keyframes to JSON..." << std::endl;
if (!FrameExtractor::runFFProbe(input_file, keyframe_json)) {
throw std::runtime_error("Error running ffprobe.");
}
std::cout << "Converting JSON to TXT..." << std::endl;
FrameExtractor::formatTimestamps(keyframe_json, keyframe_txt);
}
/*
void handleFoundTime(Time max_time, const std::string& end_time_str) {
max_time.subtract(0.1); // Сдвиг для безопасной склейки
std::string output_file = generateOutputFilename();
std::string command = "ffmpeg -v error -ss " + max_time.toString() +
" -i \"" + input_file + "\" " +
(end_time_str.empty() ? "" : "-to " + end_time_str + " ") +
"-map_metadata -1 -c copy -avoid_negative_ts make_zero \"" + output_file + "\"";
std::cout << "Executing: " << command << std::endl;
if (system(command.c_str()) != 0) throw std::runtime_error("FFmpeg failed.");
std::cout << "Done! Saved as: " << output_file << std::endl;
}
*/
void handleFoundTime(Time max_time, const std::string& end_time_str) {
max_time.subtract(0.1);
std::string output_file = generateOutputFilename();
std::string duration_part = "";
if (!end_time_str.empty()) {
Time end_time = TimestampFileParser::parseTime(end_time_str);
if (end_time.isValid()) {
// Вычисляем длительность: Конец - Начало
double diff = end_time.getTotalSeconds() - max_time.getTotalSeconds();
if (diff > 0) {
duration_part = " -t " + std::to_string(diff);
}
}
}
// Формируем команду: -ss до -i для скорости, -t для точной длительности
std::string command = "ffmpeg -v error -ss " + max_time.toString() +
" -i \"" + input_file + "\" " +
duration_part +
" -map_metadata -1 -c copy -avoid_negative_ts make_zero \"" + output_file + "\"";
std::cout << "Executing: " << command << std::endl;
if (system(command.c_str()) != 0) throw std::runtime_error("FFmpeg failed.");
}
/*
void generateAndRunFFmpegCommand(const std::string& end_time_str) {
std::string output_file = generateOutputFilename();
std::string command = "ffmpeg -v error -i \"" + input_file + "\" -map_metadata -1 " +
(end_time_str.empty() ? "" : "-to " + end_time_str + " ") +
"-c copy \"" + output_file + "\"";
if (system(command.c_str()) != 0) throw std::runtime_error("FFmpeg failed.");
}
*/
void generateAndRunFFmpegCommand(const std::string& end_time_str) {
std::string output_file = generateOutputFilename();
std::string limit = "";
if (!end_time_str.empty()) {
limit = " -to " + end_time_str; // Здесь -to работает корректно, так как нет -ss
}
std::string command = "ffmpeg -v error -i \"" + input_file + "\" -map_metadata -1" +
limit + " -c copy \"" + output_file + "\"";
if (system(command.c_str()) != 0) throw std::runtime_error("FFmpeg failed.");
}
std::string generateOutputFilename() {
std::string ext = TimeUtils::getFileExtension(input_file);
return input_file.substr(0, input_file.size() - ext.size()) + "." + TimeUtils::getCurrentDateTimeString() + ext;
}
bool checkIfFileExists(const std::string& f) { std::ifstream file(f); return file.good(); }
};
int main(int argc, char* argv[]) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <input_file> <time_start> [time_end]" << std::endl;
return 1;
}
try {
Application app(argv[1]);
app.process(argv[2], (argc > 3 ? argv[3] : ""));
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
return 1;
}
return 0;
}
Re: Сохранить фрагмент из видеофайла (нарезка на фрагменты)
Добавлено: 29 янв 2026, 07:07
ya
splitter5.cpp
Код: Выделить всё
#include <iostream>
#include <iomanip>
#include <sstream>
#include <vector>
#include <string>
#include <fstream>
#include <cstdlib>
#include <algorithm>
#include <ctime>
#include <tuple>
#include <json-c/json.h>
// Класс для корректной работы с временем
class Time {
private:
int hours, minutes;
double seconds;
public:
Time(int h = 0, int m = 0, double s = 0.0) {
if (h < 0 && m < 0 && s < 0) { // Для инициализации невалидного состояния
hours = -1; minutes = -1; seconds = -1.0;
return;
}
double total = h * 3600.0 + m * 60.0 + s;
if (total < 0) total = 0;
hours = static_cast<int>(total / 3600);
minutes = static_cast<int>((total - hours * 3600) / 60);
seconds = total - (hours * 3600) - (minutes * 60);
}
std::string toString() const {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << hours << ":"
<< std::setw(2) << std::setfill('0') << minutes << ":"
<< std::fixed << std::setprecision(6) << std::setfill('0') << seconds;
return ss.str();
}
bool isValid() const { return hours >= 0; }
double getTotalSeconds() const { return hours * 3600.0 + minutes * 60.0 + seconds; }
void subtract(double sec) {
double total = getTotalSeconds() - sec;
*this = Time(0, 0, total);
}
};
class TimeUtils {
public:
static std::string getCurrentDateTimeString() {
std::time_t now = std::time(nullptr);
std::tm* local_time = std::localtime(&now);
std::ostringstream oss;
oss << std::put_time(local_time, "%Y.%m.%d_%H-%M-%S");
return oss.str();
}
};
class FrameExtractor {
public:
static bool runFFProbe(const std::string& input, const std::string& output) {
std::string cmd = "ffprobe -v error -select_streams v:0 -skip_frame nokey "
"-show_entries frame=best_effort_timestamp_time "
"-of json \"" + input + "\" > \"" + output + "\"";
return system(cmd.c_str()) == 0;
}
static void formatTimestamps(const std::string& json_f, const std::string& txt_f) {
std::ifstream infile(json_f);
if (!infile.is_open()) return;
std::string content((std::istreambuf_iterator<char>(infile)), std::istreambuf_iterator<char>());
infile.close();
struct json_object *parsed_json = json_tokener_parse(content.c_str());
struct json_object *frames;
if (parsed_json && json_object_object_get_ex(parsed_json, "frames", &frames)) {
std::ofstream outfile(txt_f);
for (size_t i = 0; i < json_object_array_length(frames); i++) {
struct json_object *frame = json_object_array_get_idx(frames, i);
struct json_object *ts;
if (json_object_object_get_ex(frame, "best_effort_timestamp_time", &ts))
outfile << json_object_get_string(ts) << std::endl;
}
}
if (parsed_json) json_object_put(parsed_json);
}
};
class TimestampFileParser {
public:
static Time parseTime(const std::string& s) {
if (s.empty()) return Time(-1, -1, -1);
if (s.find(':') == std::string::npos) {
try { return Time(0, 0, std::stod(s)); } catch (...) { return Time(-1, -1, -1); }
}
int h, m; double sec; char c1, c2;
std::istringstream ss(s);
if (ss >> h >> c1 >> m >> c2 >> sec) return Time(h, m, sec);
return Time(-1, -1, -1);
}
static std::vector<Time> readKeyframes(const std::string& f) {
std::ifstream file(f);
std::vector<Time> tms;
std::string line;
while (std::getline(file, line)) {
Time t = parseTime(line);
if (t.isValid()) tms.push_back(t);
}
return tms;
}
};
class Application {
std::string input_file, key_txt, key_json;
public:
Application(const std::string& f) : input_file(f) {
key_txt = f + "_keyframes.txt";
key_json = f + "_keyframes.json";
}
void process(const std::string& start_s, const std::string& end_s) {
if (!checkFile(key_txt)) {
std::cout << "[Info] Scanning for keyframes..." << std::endl;
FrameExtractor::runFFProbe(input_file, key_json);
FrameExtractor::formatTimestamps(key_json, key_txt);
}
Time user_start = TimestampFileParser::parseTime(start_s);
auto keys = TimestampFileParser::readKeyframes(key_txt);
Time best_start(0,0,0);
for (auto& k : keys) {
if (k.getTotalSeconds() < user_start.getTotalSeconds()) best_start = k;
else break;
}
best_start.subtract(0.1);
std::string ext = input_file.substr(input_file.find_last_of("."));
std::string output = input_file.substr(0, input_file.find_last_of(".")) + "." + TimeUtils::getCurrentDateTimeString() + ext;
std::string dur_cmd = "";
double duration = 0;
if (!end_s.empty()) {
Time user_end = TimestampFileParser::parseTime(end_s);
duration = user_end.getTotalSeconds() - best_start.getTotalSeconds();
if (duration > 0) dur_cmd = " -t " + std::to_string(duration);
}
std::cout << "\n==========================================" << std::endl;
std::cout << " РЕЗКА ВИДЕО ПО КЛЮЧЕВЫМ КАДРАМ" << std::endl;
std::cout << "==========================================" << std::endl;
std::cout << "Старт (ключевой): " << best_start.toString() << std::endl;
std::cout << "Длительность: " << (duration > 0 ? Time(0,0,duration).toString() : "До конца") << std::endl;
std::cout << "Выходной файл: " << output << std::endl;
std::cout << "==========================================\n" << std::endl;
std::string cmd = "ffmpeg -ss " + best_start.toString() + " -i \"" + input_file + "\"" +
dur_cmd + " -map_metadata -1 -c copy -avoid_negative_ts make_zero \"" + output + "\"";
system(cmd.c_str());
std::cout << "\n[Success] Готово!" << std::endl;
}
bool checkFile(const std::string& f) { std::ifstream ifs(f); return ifs.good(); }
};
int main(int argc, char** argv) {
if (argc < 3) {
std::cerr << "Usage: " << argv[0] << " <file> <start_time> [end_time]" << std::endl;
return 1;
}
try {
Application app(argv[1]);
app.process(argv[2], argc > 3 ? argv[3] : "");
} catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
}
return 0;
}
Makefile
Код: Выделить всё
CXX = g++
CXXFLAGS = -std=c++11 -Wall -Wextra $(shell pkg-config --cflags json-c)
LDFLAGS = $(shell pkg-config --libs json-c)
TARGET = splitter
SRCS = splitter5.cpp
OBJS = $(SRCS:.cpp=.o)
all: $(TARGET)
$(TARGET): $(OBJS)
$(CXX) $(OBJS) -o $(TARGET) $(LDFLAGS)
%.o: %.cpp
$(CXX) $(CXXFLAGS) -c $< -o $@
clean:
rm -f $(OBJS) $(TARGET)