해당 내용은 아래 깃허브에 정리해 두었습니다!
디렉토리 관리 웹 페이지의 마지막!
기능 부분을 진행해 보겠습니다.
구현한 기능으로는 아래와 같습니다.
- 파일 업로드
- 파일 다운로드
- 파일 삭제
- 디렉토리 생성
- 디렉토리 압축/해제
- 데이터 수 확인
- 이미지 미리보기
- 영상 변환 및 샘플 출력
위의 기능들은 대부분 python 명령어로 실행 시켜 처리하는 방식으로 구현하여 보았습니다.
EX) 아래처럼 command를 실행시키는 함수를 만들고
ffmpeg_command = [ # 비디오에서 1프레임 샘플 전송
'ffmpeg',
'-i', savepath,
'-vf', f'eq=saturation={1+saturation/100}:brightness={brightness/100}:contrast={1+contrast/100}',
'-frames:v', '1',
'./static/sample.jpg'
]
subprocess.check_output(ffmpeg_command, text=True)
그 함수를 html script에서 아래처럼 실행!
const response = await fetch(`/download_file?file_path=${encodeURIComponent(filePath)}`);
구현
- 파일 업로드 다운로드
Shutil 라이브러리를 이용하여 다운로도와 업로드를 구현해 보았습니다.
#파일 업로드
@router.post("/upload_file")
async def upload_file(file: UploadFile,savepath : str):
# 업로드된 파일 정보 출력
upload_folder = Path(savepath)## ++ /User 1 ~ 5
upload_folder.mkdir(parents=True, exist_ok=True) # 업로드 폴더가 없으면 생성
file_path = upload_folder / file.filename
# 업로드된 파일을 서버에 저장
with file_path.open("wb") as buffer:
shutil.copyfileobj(file.file, buffer)
# 파일 다운로드
@router.get("/download_file")
async def download_file(file_path: str):
file_path_on_server = Path(file_path)
print(file_path)
# 파일이 존재하면 해당 파일을 반환
if file_path_on_server.exists():
return FileResponse(file_path_on_server)
return {"error": "File not found"}
다운로드는 현재 선택한 파일을 다운 받고,
업로드시에는 아래처럼 파일을 선택하여 업로드!
- 파일삭제
@router.post("/dir/Del") # 삭제 버튼 만들것
async def Del_file(file_path: str):
Del_command = [
'rm',
'-r',
file_path
]
subprocess.check_output(Del_command, text=True)
- 디렉토리 생성
@router.post("/dir/mkdir")# 디렉토리 생성
async def mkdir(directory_path : str):
if not os.path.exists(directory_path):
os.mkdir(directory_path)
print(f"디렉토리 '{directory_path}' 생성됨")
else:
print(f"디렉토리 '{directory_path}' 이미 존재함")
- 압축해제
Zipfile 라이브러리를 사용하여 실행하는데...
** 문제 ** 리눅스환경에서 압축한 파일과 윈도우 환경에서 압축한 파일의 encoding이 같지 않아... 사용할때 유의!
# 압축
@router.post("/dir/zip")
async def zip(directory_path : str, sort: str):
if sort=='0': # 파일
file_name = os.path.basename(directory_path)
zip_file_path = os.path.join(os.path.dirname(directory_path), f"{os.path.splitext(file_name)[0]}.zip")
# 압축 실행
with zipfile.ZipFile(zip_file_path, 'w') as zipf:
arcname = os.path.basename(directory_path)
zipf.write(directory_path, arcname)
else: # 폴더 압축
dir_name = os.path.basename(directory_path)
parent_dir = os.path.dirname(directory_path)
# 압축 파일 경로
zip_file_path = os.path.join(parent_dir, dir_name + ".zip")
with zipfile.ZipFile(zip_file_path, 'w') as zipf:
for root, _, files in os.walk(directory_path):
for file in files:
zipf.write(os.path.join(root, file), os.path.relpath(os.path.join(root, file), os.path.join(directory_path, '..')))
@router.post("/dir/Unzip")# 압축해제
async def Unzip(file_path : str):
extract_to_directory = os.path.dirname(file_path)
with zipfile.ZipFile(file_path, 'r') as zip_ref:
for file_info in zip_ref.infolist():
zip_ref.extract(file_info, extract_to_directory)
new_file_path = os.path.join(extract_to_directory, os.path.basename(file_path).split('.')[0])
- 데이터 수 측정
일단은 jpg데이터의 수만 카운트 해주기로 하였습니다.
@router.post("/dir/Count") ## 데이터 수
async def count_jpg_files(directory : str): ## 이미지 count
directory="./static"+directory
all_files = os.listdir(directory)
jpg_count = 0
directory_count = 0
for root, dirs, files in os.walk(directory):
jpg_count += len([file for file in files if file.lower().endswith(".jpg")])
directory_count += len(dirs)
return JSONResponse(content={"jpg_count": jpg_count})
- 이미지 미리보기
따로 python 함수를 생성하지 않고, 클릭시 바로 사진을 변경하는 코드로 구성!
PreviewButton.addEventListener('click', async () => { // 미리보기 실행
const Dir=document.getElementById('last_action_link');
const savepath = Dir.value;
const alldir = savepath.split('/');
const fileName = alldir.pop(); // 이름
const sort=fileName.split('.').reverse()[0];
console.log(sort)
if(image_format_List.includes(sort)){
Pre_popup.style.display='block';
imageElement.src = './static'+savepath;
document.querySelector(".background").className = "background show";
}
else{
console.log("사진만");
}
});
- 영상 변환 및 샘플 출력
이 부분은 ffmpeg 라이브러리를 사용하여 구성해 보았습니다.
기본적으로 영상만 가능 하게 구성하였고
아래처럼 영상코덱, 포맷, 크기, 비트레이트, 채도 명도 명암을 조절 할 수 있습니다.
샘플 버튼을 이용해서 현재 영상에 대한 변환 데이터를 바로 받아 볼 수 있고, 변환 버튼을 눌러
영상이름 + 현재 시간 으로 새로운 영상이 만들어 지게 됩니다.
함수는 아래처럼 구성해 주었고, 각각의 콤보박스에서 값을 불러와 ffmpeg 커맨드로 전달해 주었습니다.
@router.post("/dir/Sample") # 샘플 보내기
async def ffmpeg_sample(request: Request):
data = await request.json()
file_path = data.get('file_path')
saturation = float(data.get('saturation', 1.0))
brightness = float(data.get('brightness', 0.0))
contrast = float(data.get('contrast', 1.0))
#checkVideo=int(data.get('check',0))
savepath = './static' + file_path
# 삭제
file_path='./static/sample.jpg'
try:
# 파일이 존재하는지 확인
if os.path.exists(file_path):
# 파일 삭제
os.remove(file_path)
print(f"File '{file_path}' deleted successfully.")
else:
print(f"File '{file_path}' not found.")
except Exception as e:
print(f"An error occurred while deleting the file: {str(e)}")
ffmpeg_command = [ # 비디오에서 1프레임 샘플 전송
'ffmpeg',
'-i', savepath,
'-vf', f'eq=saturation={1+saturation/100}:brightness={brightness/100}:contrast={1+contrast/100}',
'-frames:v', '1',
'./static/sample.jpg'
]
print("savepath : " + savepath)
subprocess.check_output(ffmpeg_command, text=True)
@router.post("/dir/Conver") # 파일 변환
async def ffmpeg_Conversion(request: Request):
data = await request.json()
file_path = data.get('file_path') #변형할 파일
saturation = float(data.get('saturation', 1.0))
brightness = float(data.get('brightness', 0.0))
contrast = float(data.get('contrast', 1.0))
size = data.get('size','3840x2160')
bitlayer = data.get('bitlayer',8000)
codec = data.get('codec','libx264')
formatstr=data.get('formatstr','MP4')
print("--------------------------------------------------------")
print(formatstr)
savepath = './static' + file_path
directory = os.path.dirname(savepath)
last_directory = os.path.basename(savepath)
last_directory=str(last_directory).split('.')[0]
print("last_directory : ---------------------" + last_directory)
# 날짜와 시간을 형식에 맞게 포맷팅
current_datetime = datetime.datetime.now()
formatted_datetime = current_datetime.strftime('%Y-%m-%d-%H-%M-%S-%f')
ffmpeg_command = [
'ffmpeg',
'-i', savepath, ## 파일 위치
'-vf', f'eq=saturation={1+saturation/100}:brightness={brightness/100}:contrast={1+contrast/100}',
'-s', size,
'-c:v', codec,
'-preset', 'medium',
'-b:v', bitlayer,
directory+'/'+last_directory+"_"+formatted_datetime+"."+formatstr
]
subprocess.check_output(ffmpeg_command, text=True)
주요기능들은 여기까지!
실행 및 더더 자세한 내용이 필요하다면!
아래 깃허브에서 다운 받아 실행 해 주세요!
끝!
틀린 점이 있다면 댓 달아주세요!
'공부공부 > 2023 쌓여가는 나의 지식~' 카테고리의 다른 글
MediaPipe와 Yolo모델을 이용한 사람 관절 오토 라벨링 [Labelme Tool 사용 및 수정(3)] (2) | 2023.12.21 |
---|---|
블렌더를 이용해 간단한 3D 모델 만들기 (0) | 2023.12.09 |
(FastApi & Tree view)를 이용한 디렉토리 관리 웹 페이지 구축 (1) - GUI 관련 (0) | 2023.12.08 |
Fastapi를 이용한 웹페이지 구성 (2) - 웹 페이지 연결 및 구성 & Get/Post (1) | 2023.12.07 |
Fastapi를 이용한 웹페이지 구성 (1) - 설치 및 사용 (1) | 2023.12.06 |
댓글