Toggle navigation
Toggle navigation
This project
Loading...
Sign in
김혁우
/
design_project-automatic_video_editing_program
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Builds
Commits
Issue Boards
Authored by
Hyukwoo Kim
2020-12-17 00:01:15 +0900
Browse Files
Options
Browse Files
Download
Email Patches
Plain Diff
Commit
c2e4659cbab8b5b5d7fa71a15f13541c45e2a4ab
c2e4659c
0 parents
file registration
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
993 additions
and
0 deletions
aditor3.5.py
aditor3.5.py
0 → 100644
View file @
c2e4659
# -*- coding: utf-8 -*-
# Form implementation generated from reading ui file 'Aditor_Ui_1.1.ui'
#
# Created by: PyQt5 UI code generator 5.15.1
#
# WARNING: Any manual changes made to this file will be lost when pyuic5 is
# run again. Do not edit this file unless you know what you are doing.
from
PyQt5
import
QtCore
,
QtGui
,
QtWidgets
from
PyQt5.QtWidgets
import
QApplication
,
QMainWindow
,
QMainWindow
,
QFileDialog
,
QVBoxLayout
,
QInputDialog
,
QMessageBox
,
QAction
import
sys
import
cv2
from
PyQt5.QtCore
import
QThread
import
numpy
as
np
import
pandas
as
pd
from
time
import
sleep
from
threading
import
Timer
,
Thread
,
Event
from
matplotlib.figure
import
Figure
from
matplotlib.backends.backend_qt5agg
import
FigureCanvasQTAgg
as
FigureCanvas
class
perpetualTimer
():
#정해진 시간마다(주기) function수행
def
__init__
(
self
,
t
,
hFunction
):
self
.
t
=
t
self
.
hFunction
=
hFunction
self
.
thread
=
Timer
(
self
.
t
,
self
.
handle_function
)
print
(
"timer initate"
)
def
handle_function
(
self
):
self
.
hFunction
()
self
.
thread
=
Timer
(
self
.
t
,
self
.
handle_function
)
self
.
thread
.
start
()
def
start
(
self
):
self
.
thread
.
start
()
def
cancel
(
self
):
self
.
thread
.
cancel
()
class
workerThread
(
QThread
):
updatedM
=
QtCore
.
pyqtSignal
(
int
)
def
__init__
(
self
,
mw
):
self
.
mw
=
mw
#print("thread initialized")
QThread
.
__init__
(
self
)
def
__del__
(
self
):
self
.
wait
()
def
run
(
self
):
# print("run")
itr
=
0
QApplication
.
processEvents
()
while
self
.
mw
.
isRun
:
itr
+=
1
# print("waiting")
#print("frameID"+str(self.mw.frameID))
#print("endframe"+str(self.mw.endframe))
if
self
.
mw
.
isthreadActive
and
self
.
mw
.
isbusy
==
False
and
self
.
mw
.
frameID
!=
self
.
mw
.
cap
.
get
(
cv2
.
CAP_PROP_POS_FRAMES
):
# print(itr)\
#print("in 재생중")
if
np
.
abs
(
self
.
mw
.
frameID
-
self
.
mw
.
cap
.
get
(
cv2
.
CAP_PROP_POS_FRAMES
))
>
1
:
self
.
mw
.
cap
.
set
(
cv2
.
CAP_PROP_POS_FRAMES
,
self
.
mw
.
frameID
)
if
self
.
mw
.
frameID
>=
self
.
mw
.
endframe
-
1
:
#끝에서 멈춰주는 기능
if
not
self
.
mw
.
timer
is
None
:
print
(
"end"
)
print
(
self
.
mw
.
frameID
)
print
(
self
.
mw
.
horizontalSlider
.
value
())
self
.
mw
.
timer
.
cancel
()
self
.
mw
.
startButton
.
setEnabled
(
True
)
self
.
mw
.
pauseButton
.
setEnabled
(
False
)
self
.
mw
.
isthreadActive
=
False
self
.
mw
.
frameID
=
self
.
mw
.
endframe
-
1
if
self
.
mw
.
timer
is
None
:
self
.
mw
.
frameID
+=
1
self
.
mw
.
isbusy
=
True
sf
=
self
.
mw
.
scaleFactor
ret
,
image
=
self
.
mw
.
cap
.
read
()
self
.
mw
.
limg
=
image
if
sf
<=
0
:
self
.
mw
.
isbusy
=
False
continue
if
ret
==
False
:
self
.
mw
.
isthreadActive
=
False
self
.
mw
.
isbusy
=
False
continue
nchannel
=
image
.
shape
[
2
]
limg2
=
cv2
.
cvtColor
(
image
,
cv2
.
COLOR_RGB2BGR
)
timg
=
cv2
.
resize
(
limg2
,
(
int
(
sf
*
limg2
.
shape
[
1
]),
int
(
sf
*
limg2
.
shape
[
0
])))
limage
=
QtGui
.
QImage
(
timg
.
data
,
timg
.
shape
[
1
],
timg
.
shape
[
0
],
nchannel
*
timg
.
shape
[
1
],
QtGui
.
QImage
.
Format_RGB888
)
if
self
.
mw
.
resizegoing
==
False
:
self
.
mw
.
label
.
setPixmap
(
QtGui
.
QPixmap
(
limage
))
# self.label.setPixmap(QtGui.QPixmap(limage))
if
not
self
.
mw
.
sliderbusy
and
not
self
.
mw
.
sliderbusy2
:
self
.
updatedM
.
emit
(
self
.
mw
.
frameID
)
QApplication
.
processEvents
()
self
.
mw
.
isbusy
=
False
else
:
#print("in 멈춤!!!")
if
self
.
mw
.
isthreadActive
and
self
.
mw
.
timer
is
None
:
self
.
mw
.
frameID
+=
1
sleep
(
1.0
/
50
)
class
Ui_MainWindow
(
object
):
def
setupUi
(
self
,
MainWindow
):
MainWindow
.
setObjectName
(
"MainWindow"
)
MainWindow
.
resize
(
801
,
773
)
self
.
centralwidget
=
QtWidgets
.
QWidget
(
MainWindow
)
self
.
centralwidget
.
setMinimumSize
(
QtCore
.
QSize
(
801
,
732
))
self
.
centralwidget
.
setObjectName
(
"centralwidget"
)
self
.
horizontalLayoutWidget
=
QtWidgets
.
QWidget
(
self
.
centralwidget
)
self
.
horizontalLayoutWidget
.
setGeometry
(
QtCore
.
QRect
(
10
,
10
,
781
,
41
))
self
.
horizontalLayoutWidget
.
setObjectName
(
"horizontalLayoutWidget"
)
self
.
horizontalLayout_4b
=
QtWidgets
.
QHBoxLayout
(
self
.
horizontalLayoutWidget
)
self
.
horizontalLayout_4b
.
setContentsMargins
(
0
,
0
,
0
,
0
)
self
.
horizontalLayout_4b
.
setObjectName
(
"horizontalLayout_4b"
)
self
.
openVideoButton
=
QtWidgets
.
QPushButton
(
self
.
horizontalLayoutWidget
)
self
.
openVideoButton
.
setToolTip
(
"편집할 비디오를 선택하고 엽니다."
)
self
.
openVideoButton
.
setObjectName
(
"openVideoButton"
)
self
.
horizontalLayout_4b
.
addWidget
(
self
.
openVideoButton
)
self
.
openDataButton
=
QtWidgets
.
QPushButton
(
self
.
horizontalLayoutWidget
)
self
.
openDataButton
.
setToolTip
(
"편집할 비디오와 관련된 데이터 파일을 선택하고 엽니다. csv 파일을 받습니다. 데이터 파일로 승률데이터(스포츠 경기 영상에 해당할 경우), 유튜브 댓글 데이터, 임의로 작성한 수치 데이터를 사용 가능합니다.
\n
*임의로 작성한 데이터는 시계열 데이터여야 합니다.
\n
*데이터가 필수적이지는 않습니다. 데이터를 넣지 않아도 두가지 기능(Check on Timeline, Export)을 이용할 수 있습니다."
)
self
.
openDataButton
.
setObjectName
(
"openDataButton"
)
self
.
horizontalLayout_4b
.
addWidget
(
self
.
openDataButton
)
self
.
checkOnTimelineButton
=
QtWidgets
.
QPushButton
(
self
.
horizontalLayoutWidget
)
self
.
checkOnTimelineButton
.
setToolTip
(
"입력된 영상의 추천 편집 지점을 Timeline에 표시해줍니다."
)
self
.
checkOnTimelineButton
.
setObjectName
(
"checkOnTimelineButton"
)
self
.
horizontalLayout_4b
.
addWidget
(
self
.
checkOnTimelineButton
)
self
.
exportButton
=
QtWidgets
.
QPushButton
(
self
.
horizontalLayoutWidget
)
self
.
exportButton
.
setToolTip
(
"추천 편집 지점(Timeline에 체크된 부분)을 모아 하나의 영상으로 내보냅니다."
)
self
.
exportButton
.
setObjectName
(
"exportButton"
)
self
.
horizontalLayout_4b
.
addWidget
(
self
.
exportButton
)
self
.
verticalLayoutWidget
=
QtWidgets
.
QWidget
(
self
.
centralwidget
)
self
.
verticalLayoutWidget
.
setGeometry
(
QtCore
.
QRect
(
10
,
60
,
781
,
411
))
self
.
verticalLayoutWidget
.
setObjectName
(
"verticalLayoutWidget"
)
self
.
verticalLayout_video
=
QtWidgets
.
QVBoxLayout
(
self
.
verticalLayoutWidget
)
self
.
verticalLayout_video
.
setContentsMargins
(
0
,
0
,
0
,
0
)
self
.
verticalLayout_video
.
setObjectName
(
"verticalLayout_video"
)
self
.
label
=
QtWidgets
.
QLabel
(
self
.
verticalLayoutWidget
)
self
.
label
.
setAlignment
(
QtCore
.
Qt
.
AlignCenter
)
self
.
label
.
setObjectName
(
"label"
)
self
.
verticalLayout_video
.
addWidget
(
self
.
label
)
self
.
verticalLayoutWidget_2
=
QtWidgets
.
QWidget
(
self
.
centralwidget
)
self
.
verticalLayoutWidget_2
.
setGeometry
(
QtCore
.
QRect
(
10
,
530
,
781
,
131
))
self
.
verticalLayoutWidget_2
.
setObjectName
(
"verticalLayoutWidget_2"
)
self
.
verticalLayout_bottom
=
QtWidgets
.
QVBoxLayout
(
self
.
verticalLayoutWidget_2
)
self
.
verticalLayout_bottom
.
setContentsMargins
(
0
,
0
,
0
,
0
)
self
.
verticalLayout_bottom
.
setObjectName
(
"verticalLayout_bottom"
)
self
.
tabWidget
=
QtWidgets
.
QTabWidget
(
self
.
verticalLayoutWidget_2
)
self
.
tabWidget
.
setObjectName
(
"tabWidget"
)
self
.
tab
=
QtWidgets
.
QWidget
()
self
.
tab
.
setToolTip
(
"추천 편집 지점을 나타내는 타임라인입니다."
)
self
.
tab
.
setObjectName
(
"tab"
)
self
.
label_2
=
QtWidgets
.
QLabel
(
self
.
tab
)
self
.
label_2
.
setGeometry
(
QtCore
.
QRect
(
0
,
0
,
771
,
101
))
self
.
label_2
.
setAlignment
(
QtCore
.
Qt
.
AlignCenter
)
self
.
label_2
.
setObjectName
(
"label_2"
)
self
.
tabWidget
.
addTab
(
self
.
tab
,
""
)
self
.
tab_2
=
QtWidgets
.
QWidget
()
self
.
tab_2
.
setToolTip
(
"데이터 파일과 영상에서 추출된 데이터를 바탕으로 하이라이트인 정도를 평가하는 그래프를 보여줍니다."
)
self
.
tab_2
.
setObjectName
(
"tab_2"
)
self
.
label_3
=
QtWidgets
.
QLabel
(
self
.
tab_2
)
self
.
label_3
.
setGeometry
(
QtCore
.
QRect
(
0
,
0
,
771
,
101
))
self
.
label_3
.
setAlignment
(
QtCore
.
Qt
.
AlignCenter
)
self
.
label_3
.
setObjectName
(
"label_3"
)
self
.
tabWidget
.
addTab
(
self
.
tab_2
,
""
)
self
.
verticalLayout_bottom
.
addWidget
(
self
.
tabWidget
)
self
.
progressBar
=
QtWidgets
.
QProgressBar
(
self
.
centralwidget
)
self
.
progressBar
.
setGeometry
(
QtCore
.
QRect
(
10
,
700
,
781
,
20
))
self
.
progressBar
.
setProperty
(
"value"
,
24
)
self
.
progressBar
.
setToolTip
(
"두가지 기능(Check on Timeline, Export)의 진행 상황을 나타냅니다."
)
self
.
progressBar
.
setObjectName
(
"progressBar"
)
self
.
horizontalLayoutWidget_2
=
QtWidgets
.
QWidget
(
self
.
centralwidget
)
self
.
horizontalLayoutWidget_2
.
setGeometry
(
QtCore
.
QRect
(
10
,
480
,
781
,
44
))
self
.
horizontalLayoutWidget_2
.
setObjectName
(
"horizontalLayoutWidget_2"
)
self
.
horizontalLayout_2b
=
QtWidgets
.
QHBoxLayout
(
self
.
horizontalLayoutWidget_2
)
self
.
horizontalLayout_2b
.
setContentsMargins
(
0
,
0
,
0
,
0
)
self
.
horizontalLayout_2b
.
setObjectName
(
"horizontalLayout_2b"
)
self
.
startButton
=
QtWidgets
.
QPushButton
(
self
.
horizontalLayoutWidget_2
)
self
.
startButton
.
setToolTip
(
"동영상을 재생하는 버튼입니다."
)
self
.
startButton
.
setObjectName
(
"startButton"
)
self
.
horizontalLayout_2b
.
addWidget
(
self
.
startButton
)
self
.
pauseButton
=
QtWidgets
.
QPushButton
(
self
.
horizontalLayoutWidget_2
)
self
.
pauseButton
.
setToolTip
(
"동영상을 일시정지하는 버튼입니다."
)
self
.
pauseButton
.
setObjectName
(
"pauseButton"
)
self
.
horizontalLayout_2b
.
addWidget
(
self
.
pauseButton
)
self
.
horizontalSlider
=
QtWidgets
.
QSlider
(
self
.
centralwidget
)
self
.
horizontalSlider
.
setGeometry
(
QtCore
.
QRect
(
18
,
670
,
762
,
22
))
self
.
horizontalSlider
.
setOrientation
(
QtCore
.
Qt
.
Horizontal
)
self
.
horizontalSlider
.
setToolTip
(
"동영상 재생 지점을 선택할 수 있습니다. Timeline에 체크된 부분을 확인할 때 쓰일 것입니다"
)
self
.
horizontalSlider
.
setObjectName
(
"horizontalSlider"
)
MainWindow
.
setCentralWidget
(
self
.
centralwidget
)
self
.
menubar
=
QtWidgets
.
QMenuBar
(
MainWindow
)
self
.
menubar
.
setGeometry
(
QtCore
.
QRect
(
0
,
0
,
801
,
21
))
self
.
menubar
.
setObjectName
(
"menubar"
)
self
.
menuFile
=
QtWidgets
.
QMenu
(
self
.
menubar
)
self
.
menuFile
.
setToolTip
(
"New Project: 현재 올려진 동영상과 타임라인을 지우고 초기화 시킵니다.
\n
Settings: 기타 설정을 변경할 수 있습니다. Check on Timeline의 민감도 설정을 할 수 있습니다.
\n
Exit: 프로그램을 종료합니다."
)
self
.
menuFile
.
setObjectName
(
"menuFile"
)
self
.
menuTools
=
QtWidgets
.
QMenu
(
self
.
menubar
)
self
.
menuTools
.
setToolTip
(
"Add YouTube Link: 편집할 영상이 유튜브에 업로드 되어 있다면, 그 영상의 URL을 입력하여 댓글 데이터를 자동으로 가져옵니다."
)
self
.
menuTools
.
setObjectName
(
"menuTools"
)
self
.
menuHelp
=
QtWidgets
.
QMenu
(
self
.
menubar
)
self
.
menuHelp
.
setToolTip
(
"프로그램 사용 가이드와 제작정보"
)
self
.
menuHelp
.
setObjectName
(
"menuHelp"
)
MainWindow
.
setMenuBar
(
self
.
menubar
)
self
.
statusbar
=
QtWidgets
.
QStatusBar
(
MainWindow
)
self
.
statusbar
.
setObjectName
(
"statusbar"
)
MainWindow
.
setStatusBar
(
self
.
statusbar
)
self
.
actionnew_project
=
QtWidgets
.
QAction
(
MainWindow
)
self
.
actionnew_project
.
setObjectName
(
"actionnew_project"
)
self
.
actionSetting
=
QtWidgets
.
QAction
(
MainWindow
)
self
.
actionSetting
.
setObjectName
(
"actionSetting"
)
self
.
actionExit
=
QtWidgets
.
QAction
(
MainWindow
)
self
.
actionExit
.
setObjectName
(
"actionExit"
)
self
.
actionHow_to_use
=
QtWidgets
.
QAction
(
MainWindow
)
self
.
actionHow_to_use
.
setObjectName
(
"actionHow_to_use"
)
self
.
actionAbout
=
QtWidgets
.
QAction
(
MainWindow
)
self
.
actionAbout
.
setObjectName
(
"actionAbout"
)
self
.
actionData
=
QtWidgets
.
QAction
(
MainWindow
)
self
.
actionData
.
setObjectName
(
"actionData"
)
self
.
menuFile
.
addAction
(
self
.
actionnew_project
)
self
.
menuFile
.
addAction
(
self
.
actionSetting
)
self
.
menuFile
.
addAction
(
self
.
actionExit
)
self
.
menuTools
.
addAction
(
self
.
actionData
)
self
.
menuHelp
.
addAction
(
self
.
actionHow_to_use
)
self
.
menuHelp
.
addAction
(
self
.
actionAbout
)
self
.
menubar
.
addAction
(
self
.
menuFile
.
menuAction
())
self
.
menubar
.
addAction
(
self
.
menuTools
.
menuAction
())
self
.
menubar
.
addAction
(
self
.
menuHelp
.
menuAction
())
self
.
retranslateUi
(
MainWindow
)
self
.
tabWidget
.
setCurrentIndex
(
1
)
QtCore
.
QMetaObject
.
connectSlotsByName
(
MainWindow
)
def
retranslateUi
(
self
,
MainWindow
):
_translate
=
QtCore
.
QCoreApplication
.
translate
MainWindow
.
setWindowTitle
(
_translate
(
"MainWindow"
,
"Auto Video Editor"
))
self
.
openVideoButton
.
setText
(
_translate
(
"MainWindow"
,
"Open Video"
))
self
.
openDataButton
.
setText
(
_translate
(
"MainWindow"
,
"Open Data File"
))
self
.
checkOnTimelineButton
.
setText
(
_translate
(
"MainWindow"
,
"Check on Timeline"
))
self
.
exportButton
.
setText
(
_translate
(
"MainWindow"
,
"Export"
))
self
.
label
.
setText
(
_translate
(
"MainWindow"
,
"video"
))
self
.
label_2
.
setText
(
_translate
(
"MainWindow"
,
"Timeline: 추천 편집 지점을 나타내는 타임라인입니다."
))
self
.
tabWidget
.
setTabText
(
self
.
tabWidget
.
indexOf
(
self
.
tab
),
_translate
(
"MainWindow"
,
"Timeline"
))
self
.
label_3
.
setText
(
_translate
(
"MainWindow"
,
"Data: 데이터 파일과 영상에서 추출된 데이터를 바탕으로 하이라이트인 정도를 평가하는 그래프를 보여줍니다."
))
self
.
tabWidget
.
setTabText
(
self
.
tabWidget
.
indexOf
(
self
.
tab_2
),
_translate
(
"MainWindow"
,
"Data"
))
self
.
startButton
.
setText
(
_translate
(
"MainWindow"
,
"Start"
))
self
.
pauseButton
.
setText
(
_translate
(
"MainWindow"
,
"Pause"
))
self
.
menuFile
.
setTitle
(
_translate
(
"MainWindow"
,
"File"
))
self
.
menuTools
.
setTitle
(
_translate
(
"MainWindow"
,
"Tools"
))
self
.
menuHelp
.
setTitle
(
_translate
(
"MainWindow"
,
"Help"
))
self
.
actionnew_project
.
setText
(
_translate
(
"MainWindow"
,
"New Project"
))
self
.
actionSetting
.
setText
(
_translate
(
"MainWindow"
,
"Settings"
))
self
.
actionExit
.
setText
(
_translate
(
"MainWindow"
,
"Exit"
))
self
.
actionHow_to_use
.
setText
(
_translate
(
"MainWindow"
,
"How to use"
))
self
.
actionAbout
.
setText
(
_translate
(
"MainWindow"
,
"About"
))
self
.
actionData
.
setText
(
_translate
(
"MainWindow"
,
"XML action"
))
class
WindowClass
(
QMainWindow
,
Ui_MainWindow
):
# Ui_MainWindow를 받음
resized
=
QtCore
.
pyqtSignal
()
def
__init__
(
self
):
super
()
.
__init__
()
self
.
setupUi
(
self
)
self
.
openVideoButton
.
clicked
.
connect
(
self
.
OVBtnClicked
)
self
.
startButton
.
clicked
.
connect
(
self
.
startButtonClicked
)
self
.
pauseButton
.
clicked
.
connect
(
self
.
pauseButtonclicked
)
self
.
horizontalSlider
.
sliderPressed
.
connect
(
self
.
horizontalSliderPressed
)
self
.
horizontalSlider
.
sliderReleased
.
connect
(
self
.
horizontalSliderReleased
)
self
.
horizontalSlider
.
valueChanged
.
connect
(
self
.
slider_value_changed
)
self
.
openDataButton
.
clicked
.
connect
(
self
.
ODBtnClicked
)
self
.
checkOnTimelineButton
.
clicked
.
connect
(
self
.
CTLBtnCLicked
)
self
.
exportButton
.
clicked
.
connect
(
self
.
EPBtnClicked
)
action
=
QAction
(
"&Add YouTube link"
,
self
)
self
.
menuTools
.
addAction
(
action
)
action
.
triggered
.
connect
(
self
.
AYBtnClicked
)
#버튼 설정
self
.
startButton
.
setEnabled
(
False
)
self
.
pauseButton
.
setEnabled
(
False
)
self
.
horizontalSlider
.
setEnabled
(
False
)
self
.
openDataButton
.
setEnabled
(
False
)
self
.
checkOnTimelineButton
.
setEnabled
(
False
)
self
.
exportButton
.
setEnabled
(
False
)
self
.
progressBar
.
setValue
(
0
)
#프레임 정보
self
.
frameID
=
0
#현재 프레임
self
.
stframe
=
0
#시작 프레임
self
.
endframe
=
0
#끝 프레임
self
.
fps
=
0
#초당 프레임
#영상 크기 조절
self
.
scaleFactor
=
0.5
# thread
self
.
wthread
=
workerThread
(
self
)
self
.
wthread
.
updatedM
.
connect
(
self
.
horizontalSliderSet
)
self
.
wthread
.
start
()
#기타 멤버 변수들
self
.
limg
=
np
.
zeros
((
1
,
1
,
1
))
self
.
isbusy
=
0
self
.
frameHeight
=
1
self
.
frameWidth
=
1
self
.
isRun
=
True
self
.
resizegoing
=
False
self
.
sliderbusy
=
False
self
.
sliderbusy2
=
False
self
.
linebusy
=
False
self
.
cap
=
None
self
.
timer
=
None
self
.
isvideo
=
False
self
.
videoFileName
=
""
self
.
isthreadActive
=
False
#데이터
self
.
clip
=
0
self
.
max_slice
=
5
self
.
threshold
=
0.4
self
.
inputData
=
pd
.
DataFrame
()
self
.
audioData
=
pd
.
DataFrame
()
self
.
commentsData
=
0
self
.
highlightData
=
pd
.
DataFrame
()
self
.
isdata
=
False
self
.
iscomments
=
False
self
.
videoID
=
""
#그리기
layout1
=
QVBoxLayout
()
layout2
=
QVBoxLayout
()
self
.
figure1
=
Figure
()
self
.
figure2
=
Figure
()
self
.
label_2
.
canvas
=
FigureCanvas
(
self
.
figure1
)
self
.
label_3
.
canvas
=
FigureCanvas
(
self
.
figure2
)
layout1
.
addWidget
(
self
.
label_2
.
canvas
)
layout2
.
addWidget
(
self
.
label_3
.
canvas
)
self
.
label_2
.
setLayout
(
layout1
)
self
.
label_3
.
setLayout
(
layout2
)
self
.
ax1
=
self
.
figure1
.
add_subplot
(
1
,
1
,
1
)
self
.
ax2
=
self
.
figure2
.
add_subplot
(
1
,
1
,
1
)
self
.
ax1
.
get_yaxis
()
.
set_visible
(
False
)
self
.
ax1
.
get_xaxis
()
.
set_visible
(
True
)
self
.
figure1
.
subplots_adjust
(
left
=
0.001
,
right
=
0.999
,
top
=
1.0
,
bottom
=
0.1
)
self
.
figure2
.
subplots_adjust
(
left
=
0.001
,
right
=
0.999
,
top
=
1.0
,
bottom
=
0.1
)
def
OVBtnClicked
(
self
):
self
.
isthreadActive
=
False
fileName
=
QFileDialog
.
getOpenFileName
(
None
,
caption
=
"Select Video File"
,
directory
=
QtCore
.
QDir
.
currentPath
())
if
len
(
fileName
[
0
])
>
0
:
self
.
videoFileName
=
fileName
[
0
]
self
.
cap
=
cv2
.
VideoCapture
(
fileName
[
0
])
# 비디오 캡쳐하는 부분
self
.
isvideo
=
True
else
:
return
length
=
int
(
self
.
cap
.
get
(
cv2
.
CAP_PROP_FRAME_COUNT
))
print
(
"length: "
+
str
(
length
))
self
.
fps
=
self
.
cap
.
get
(
cv2
.
CAP_PROP_FPS
)
print
(
"fps: "
+
str
(
self
.
fps
))
self
.
stframe
=
0
self
.
endframe
=
length
#self.stframe = int(self.data.values[1, 1] * self.fps)
#print("stframe: " + str(self.stframe))
#self.endframe = int(self.data.values[-1, 1] * self.fps)
#print("endframe: " + str(self.endframe))
#self.ui.horizontalSlider.setMaximum(self.endframe - self.stframe)
#self.cap.set(1, self.stframe)
#self.cap.set(1, 200)
ret
,
frame
=
self
.
cap
.
read
()
self
.
drawmin
=
1
self
.
frameID
=
self
.
stframe
self
.
limg
=
frame
self
.
frameHeight
=
frame
.
shape
[
0
]
self
.
frameWidth
=
frame
.
shape
[
1
]
nchannel
=
frame
.
shape
[
2
]
limg2
=
cv2
.
cvtColor
(
frame
,
cv2
.
COLOR_RGB2BGR
)
timg
=
cv2
.
resize
(
limg2
,
(
int
(
self
.
scaleFactor
*
limg2
.
shape
[
1
]),
int
(
self
.
scaleFactor
*
limg2
.
shape
[
0
])))
limage
=
QtGui
.
QImage
(
timg
.
data
,
timg
.
shape
[
1
],
timg
.
shape
[
0
],
nchannel
*
timg
.
shape
[
1
],
QtGui
.
QImage
.
Format_RGB888
)
self
.
label
.
setPixmap
(
QtGui
.
QPixmap
(
limage
))
self
.
startButton
.
setEnabled
(
True
)
self
.
horizontalSlider
.
setEnabled
(
True
)
self
.
openDataButton
.
setEnabled
(
True
)
self
.
checkOnTimelineButton
.
setEnabled
(
True
)
self
.
exportButton
.
setEnabled
(
False
)
self
.
horizontalSlider
.
setMaximum
(
self
.
endframe
-
self
.
stframe
)
self
.
horizontalSlider
.
setValue
(
self
.
stframe
)
self
.
isdata
=
False
def
updateFrame
(
self
):
self
.
frameID
+=
1
def
startButtonClicked
(
self
):
if
self
.
isthreadActive
:
return
self
.
startButton
.
setEnabled
(
False
)
self
.
timer
=
perpetualTimer
(
1.0
/
self
.
fps
,
self
.
updateFrame
)
self
.
timer
.
start
()
self
.
pauseButton
.
setEnabled
(
True
)
self
.
isthreadActive
=
True
print
(
"thread activatied"
)
def
pauseButtonclicked
(
self
):
if
not
self
.
isthreadActive
:
return
self
.
startButton
.
setEnabled
(
True
)
self
.
pauseButton
.
setEnabled
(
False
)
if
not
self
.
timer
is
None
:
self
.
timer
.
cancel
()
self
.
isthreadActive
=
False
def
videoSec
(
self
):
return
int
(
self
.
frameID
/
self
.
fps
)
def
horizontalSliderSet
(
self
,
cnt
):
#슬라이더 위치 업데이트
if
cnt
+
1
-
self
.
stframe
>
self
.
horizontalSlider
.
maximum
()
or
self
.
sliderbusy
or
self
.
resizegoing
:
return
self
.
sliderbusy2
=
True
self
.
horizontalSlider
.
setValue
(
cnt
+
1
-
self
.
stframe
)
tsec
=
cnt
/
self
.
fps
tmin
=
int
(
tsec
/
60
)
ttsec
=
int
(
tsec
-
60
*
tmin
)
ksec
=
tsec
-
60
*
tmin
-
ttsec
self
.
statusbar
.
showMessage
(
"Time: "
+
str
(
tmin
)
.
zfill
(
2
)
+
":"
+
str
(
ttsec
)
.
zfill
(
2
)
+
":"
+
str
(
int
(
ksec
*
100
)))
self
.
sliderbusy2
=
False
"""
def lineSliderSet(self, cnt): #그래프상 수직선 위치 업데이트
if cnt + 1 - self.stframe > self.horizontalSlider.maximum():
return
self.linebusy = True
pdraw = self.drawmin
self.drawmin -= 20
if self.drawmin < 1:
self.drawmin = 1
while (cnt + 1) / self.fps > self.data.values[self.drawmin, 1]:
self.drawmin += 1
if not self.drawmin == pdraw or pdraw == 1:
wr = ref(self.ax1.lines[5])
self.ax1.lines.remove(wr())
self.ui.bottomImage.canvas.draw()
self.ax1.plot([self.data.values[self.drawmin, 1], self.data.values[self.drawmin, 1]], [0, 3.4], 'k',
linewidth=2.0)
self.ui.bottomImage.canvas.draw()
tsec = cnt / self.fps
tmin = int(tsec / 60)
ttsec = int(tsec - 60 * tmin)
ksec = tsec - 60 * tmin - ttsec
self.ui.statusbar.showMessage(
"Frame Time: " + str(tmin).zfill(2) + ":" + str(ttsec).zfill(2) + ":" + str(int(ksec * 100)))
self.linebusy = False
"""
def
horizontalSliderPressed
(
self
):
self
.
sliderbusy
=
True
def
slider_value_changed
(
self
):
#print('slidervalue change')
self
.
horizontalSliderIncrease
(
0
)
#if not self.isthreadActive:
# print("thread is not active")
# self.horizontalSliderIncrease(0)
def
horizontalSliderIncrease
(
self
,
val
):
if
self
.
sliderbusy
or
self
.
resizegoing
:
return
self
.
sliderbusy
=
True
# print(self.horizontalSlider.value())
# self.ui.horizontalSlider.setValue(self.ui.horizontalSlider.value()+val)
# print(self.frameID)
self
.
frameID
=
self
.
stframe
+
self
.
horizontalSlider
.
value
()
-
1
# print(self.frameID)
# self.drawmin=1
if
self
.
startButton
.
isEnabled
():
self
.
cap
.
set
(
cv2
.
CAP_PROP_POS_FRAMES
,
self
.
frameID
)
ret
,
frame
=
self
.
cap
.
read
()
self
.
limg
=
frame
# self.on_zoomfit_clicked()
nchannel
=
frame
.
shape
[
2
]
limg2
=
cv2
.
cvtColor
(
frame
,
cv2
.
COLOR_RGB2BGR
)
timg
=
cv2
.
resize
(
limg2
,
(
int
(
self
.
scaleFactor
*
limg2
.
shape
[
1
]),
int
(
self
.
scaleFactor
*
limg2
.
shape
[
0
])))
limage
=
QtGui
.
QImage
(
timg
.
data
,
timg
.
shape
[
1
],
timg
.
shape
[
0
],
nchannel
*
timg
.
shape
[
1
],
QtGui
.
QImage
.
Format_RGB888
)
self
.
label
.
setPixmap
(
QtGui
.
QPixmap
(
limage
))
#self.lineSliderSet(self.frameID)
self
.
sliderbusy
=
False
def
horizontalSliderReleased
(
self
):
self
.
frameID
=
self
.
stframe
+
self
.
horizontalSlider
.
value
()
-
1
print
(
self
.
frameID
)
print
(
self
.
horizontalSlider
.
value
())
self
.
drawmin
=
1
if
self
.
startButton
.
isEnabled
():
self
.
cap
.
set
(
cv2
.
CAP_PROP_POS_FRAMES
,
self
.
frameID
)
ret
,
frame
=
self
.
cap
.
read
()
self
.
limg
=
frame
#self.on_zoomfit_clicked()
nchannel
=
frame
.
shape
[
2
]
limg2
=
cv2
.
cvtColor
(
frame
,
cv2
.
COLOR_RGB2BGR
)
timg
=
cv2
.
resize
(
limg2
,
(
int
(
self
.
scaleFactor
*
limg2
.
shape
[
1
]),
int
(
self
.
scaleFactor
*
limg2
.
shape
[
0
])))
limage
=
QtGui
.
QImage
(
timg
.
data
,
timg
.
shape
[
1
],
timg
.
shape
[
0
],
nchannel
*
timg
.
shape
[
1
],
QtGui
.
QImage
.
Format_RGB888
)
self
.
label
.
setPixmap
(
QtGui
.
QPixmap
(
limage
))
#self.lineSliderSet(self.frameID)
self
.
sliderbusy
=
False
def
ODBtnClicked
(
self
):
self
.
pauseButtonclicked
()
fileName
=
QFileDialog
.
getOpenFileName
(
None
,
caption
=
"Select Data File(only csv)"
,
directory
=
QtCore
.
QDir
.
currentPath
())
if
len
(
fileName
[
0
])
>
0
:
data
=
pd
.
read_csv
(
fileName
[
0
])
self
.
inputData
=
data
self
.
isdata
=
True
#print(self.inputData)
return
def
CTLBtnCLicked
(
self
):
#데이터 가져오기
self
.
pauseButtonclicked
()
choice
=
QMessageBox
.
question
(
self
,
''
,
'기본 설정값을 사용하겠습니까?'
,
QMessageBox
.
Yes
|
QMessageBox
.
No
)
if
choice
==
QMessageBox
.
No
:
input_max_slice
,
ok
=
QInputDialog
.
getInt
(
self
,
'단위 구간 설정'
,
'하이라이트성을 평가할 구간의 길이를 설정하세요. (초)'
)
if
ok
:
if
input_max_slice
>=
0
:
self
.
max_slice
=
input_max_slice
else
:
return
input_threshold
,
ok
=
QInputDialog
.
getDouble
(
self
,
'임계값 설정'
,
'하이라이트 포함 임계값을 설정하세요. (0~1 실수)'
)
if
ok
:
if
0
<=
input_threshold
<=
1
:
self
.
threshold
=
input_threshold
else
:
return
else
:
self
.
max_slice
=
5
self
.
threshold
=
0.4
self
.
clip
=
Clip
(
self
.
videoFileName
)
self
.
audioData
=
self
.
clip
.
getLoudSection
(
max_slice
=
self
.
max_slice
,
threshold
=
400
)
self
.
drawData
(
max_slice
=
self
.
max_slice
,
threshold
=
self
.
threshold
)
self
.
exportButton
.
setVisible
(
True
)
self
.
exportButton
.
setEnabled
(
True
)
return
#영상 내보내기
def
EPBtnClicked
(
self
):
#print(self.highlightData)
self
.
clip
.
concatVideo
(
self
.
highlightData
,
self
.
max_slice
)
return
#타임라인 그리기
#def drawTimeline(self):
# return
#데이터 그리기
def
decisionFunction
(
self
,
audioData
,
inputData
=
None
):
data
=
pd
.
DataFrame
()
#normalization(min-max scaling)
audioData
[
"energy"
]
=
(
audioData
[
"energy"
]
-
audioData
[
"energy"
]
.
min
())
/
(
audioData
[
"energy"
]
.
max
()
-
audioData
[
"energy"
]
.
min
())
if
inputData
is
None
:
data
=
audioData
else
:
self
.
inputData
.
iloc
[:,
0
]
=
(
self
.
inputData
.
iloc
[:,
0
]
-
self
.
inputData
.
iloc
[:,
0
]
.
min
())
/
(
self
.
inputData
.
iloc
[:,
0
]
.
max
()
-
self
.
inputData
.
iloc
[:,
0
]
.
min
())
self
.
inputData
=
self
.
inputData
.
reindex
(
self
.
inputData
.
index
.
repeat
(
int
(
60
/
self
.
max_slice
)))
.
assign
()
self
.
inputData
=
self
.
inputData
.
reset_index
()
#print(self.inputData)
data
=
0.9
*
audioData
.
iloc
[:,
0
]
+
0.1
*
self
.
inputData
.
iloc
[:,
1
]
data
=
data
.
to_frame
()
data
=
data
.
iloc
[:
len
(
audioData
),
0
]
data
=
data
.
to_frame
()
data
[
"start"
]
=
audioData
[
"start"
]
.
tolist
()
#result3 = pd.concat([df1, df2], axis=1)
#data.concat([data, df], axis=1)
return
data
#timeline, data 그리기
def
drawData
(
self
,
max_slice
=
10
,
threshold
=
0.4
):
if
self
.
isdata
is
False
and
self
.
isvideo
is
True
:
data
=
self
.
decisionFunction
(
self
.
audioData
)
#그릴 데이터
elif
self
.
isdata
is
True
and
self
.
isvideo
is
True
:
data
=
self
.
decisionFunction
(
self
.
audioData
,
self
.
inputData
)
#그릴 데이터
else
:
return
#ax2(Data)그리기
self
.
ax2
.
clear
()
self
.
ax2
.
set_ylim
([
0
,
1.1
])
#print(data)
ndata
=
data
.
to_numpy
()[:,
0
]
print
(
ndata
)
stretchedata
=
np
.
zeros
(
int
(
self
.
endframe
/
self
.
fps
)
+
1
)
#영상의 실제 끝으로설정
#print(stretchedata[10])
#print("check")
for
i
in
range
(
len
(
stretchedata
)):
stretchedata
[
i
]
=
ndata
[
int
(
i
/
max_slice
)]
#print(stretchedata)
self
.
ax2
.
plot
(
stretchedata
,
'-c'
)
#self.ax2.hist(data.to_numpy()[:,0], 10, histtype='stepfilled')
self
.
ax2
.
set_xlim
((
self
.
stframe
/
self
.
fps
),
int
(
self
.
endframe
/
self
.
fps
))
#print(data.to_numpy()[:,0])
#self.highlightData = data.to_numpy()[:,0]
self
.
ax2
.
plot
([
data
.
to_numpy
()[
0
,
1
],
data
.
to_numpy
()[
0
,
1
]],
[
0
,
1.1
],
'k'
,
linewidth
=
2.0
)
#self.ax1.plot([self.data.values[1, 1], self.data.values[1, 1]], [0, 3.4], 'k', linewidth=2.0)
#print(data.to_numpy()[1, 1], data.to_numpy()[-1, 1])
self
.
ax2
.
xaxis
.
set_ticks
(
np
.
arange
(
self
.
stframe
/
self
.
fps
,
self
.
endframe
/
self
.
fps
,
max_slice
))
self
.
ax2
.
xaxis
.
set_visible
(
True
)
self
.
label_3
.
canvas
.
draw
()
#ax1(Timeline)그리기
self
.
ax1
.
clear
()
self
.
ax1
.
set_ylim
([
0.5
,
1.5
])
self
.
ax1
.
set_xlim
((
self
.
stframe
/
self
.
fps
),
int
(
self
.
endframe
/
self
.
fps
))
timelinedata
=
np
.
zeros
(
int
(
self
.
endframe
/
self
.
fps
)
+
1
)
for
i
in
range
(
len
(
timelinedata
)):
if
stretchedata
[
i
]
>
threshold
:
timelinedata
[
i
]
=
1
if
self
.
iscomments
is
True
:
os
.
environ
[
'OAUTHLIB_INSECURE_TRANSPORT'
]
=
'1'
service
=
get_authenticated_service
()
comments
=
get_video_comments
(
service
,
part
=
'snippet'
,
videoId
=
self
.
videoID
,
textFormat
=
'plainText'
)
video_duration
=
get_video_duration
(
service
,
part
=
'contentDetails'
,
id
=
self
.
videoID
)
# print(video_duration)
# print(comments)
self
.
commentsData
=
make_video_timeline
(
comments
,
video_duration
,
self
.
max_slice
)
print
(
str
(
len
(
timelinedata
))
+
","
+
str
(
len
(
self
.
commentsData
)))
if
not
(
-
1
<=
len
(
timelinedata
)
/
self
.
max_slice
-
len
(
self
.
commentsData
)
<=
1
):
choice
=
QMessageBox
.
warning
(
self
,
'warning'
,
'유튜브 댓글 데이터가 올바르지 않습니다. 제외하고 진행하겠습니까?'
,
QMessageBox
.
Yes
|
QMessageBox
.
No
)
if
choice
==
QMessageBox
.
Yes
:
self
.
highlightData
=
timelinedata
self
.
iscomments
=
False
else
:
sys
.
exit
()
else
:
#commentsData반영
for
i
in
range
(
len
(
timelinedata
)):
#print(i)
if
timelinedata
[
i
]
==
0
:
#print(i/self.max_slice)
if
self
.
commentsData
[
int
(
i
/
self
.
max_slice
)]
==
1
:
timelinedata
[
i
]
=
1
print
(
self
.
commentsData
)
self
.
highlightData
=
timelinedata
self
.
ax1
.
plot
(
timelinedata
,
'*y'
)
self
.
ax1
.
set_xlim
((
self
.
stframe
/
self
.
fps
),
int
(
self
.
endframe
/
self
.
fps
))
self
.
ax1
.
xaxis
.
set_ticks
(
np
.
arange
(
self
.
stframe
/
self
.
fps
,
self
.
endframe
/
self
.
fps
,
max_slice
))
self
.
ax1
.
plot
([
data
.
to_numpy
()[
0
,
1
],
data
.
to_numpy
()[
0
,
1
]],
[
0.5
,
1.5
],
'k'
,
linewidth
=
2.0
)
self
.
label_2
.
canvas
.
draw
()
#스케일링 방법 바꾸기
return
def
AYBtnClicked
(
self
):
video_id
,
ok
=
QInputDialog
.
getText
(
self
,
'영상 ID'
,
'유튜브 영상 ID를 입력하세요. (/watch?v=~)'
)
if
not
ok
:
return
self
.
videoID
=
video_id
self
.
iscomments
=
True
#check on timeline and export
import
moviepy.editor
as
mp
import
librosa
class
Clip
:
def
__init__
(
self
,
fileName
):
self
.
clip
=
mp
.
VideoFileClip
(
fileName
)
self
.
fullFileName
=
fileName
self
.
fileName
=
fileName
[:
fileName
.
rfind
(
'.'
)]
def
getLoudSection
(
self
,
max_slice
=
10
,
threshold
=
180
):
#max_slice: 몇 초 단위로 나눌 것인지 결정
self
.
clip
.
audio
.
write_audiofile
(
self
.
fileName
+
'.wav'
)
x
,
sr
=
librosa
.
load
(
self
.
fileName
+
'.wav'
,
sr
=
16000
)
#x: 오디오 파일을 나눈(1초에 sr개로 나눔) 샘플들의 진폭이 저장됨, 샘플의 개수는 sr*영상길이
#print(x)
#print(len(x))
window_length
=
max_slice
*
sr
#한 구간에 해당하는 샘플의 개수
energy
=
np
.
array
([
sum
(
abs
(
x
[
i
:
i
+
window_length
]
**
2
))
#windwo_length구간 안에있는 모든 샘플들의 진폭의 제곱의 합->소리의 크기
for
i
in
range
(
0
,
len
(
x
),
window_length
)])
#len(x)는 sr*영상길이인데 이것을 window_length만큼 끊음 i = 0, winlength, winlength*2, winlength*3, ...
#print(energy)
#energy data를 dataframe으로 만듦
df
=
pd
.
DataFrame
(
columns
=
[
'energy'
,
'start'
,
'end'
])
row_index
=
0
for
i
in
range
(
len
(
energy
)):
value
=
energy
[
i
]
i
=
np
.
where
(
energy
==
value
)[
0
]
df
.
loc
[
row_index
,
'energy'
]
=
value
df
.
loc
[
row_index
,
'start'
]
=
i
[
0
]
*
max_slice
df
.
loc
[
row_index
,
'end'
]
=
(
i
[
0
]
+
1
)
*
max_slice
row_index
=
row_index
+
1
#print(df)
"""
if value >= threshold:
i = np.where(energy == value)[0]
df.loc[row_index, 'energy'] = value
df.loc[row_index, 'start'] = i[0] * max_slice
df.loc[row_index, 'end'] = (i[0] + 1) * max_slice
row_index = row_index + 1
print(df) #threshold를 넘은 구간이 저장됨
"""
#연속구간으로 나타내기
"""
temp = []
i = 0
j = 0
n = len(df) - 2
m = len(df) - 1
while (i <= n):
j = i + 1
while (j <= m):
if (df['end'][i] == df['start'][j]):
df.loc[i, 'end'] = df.loc[j, 'end']
temp.append(j)
j = j + 1
else:
i = j
break
df.drop(temp, axis=0, inplace=True)
print(df)
"""
return
df
def
concatVideo
(
self
,
data
,
max_slice
):
i
=
0
clips
=
[]
final1
=
[]
final2
=
[]
while
i
<
len
(
data
):
if
data
[
i
]
==
1
:
subclip
=
self
.
clip
.
subclip
(
i
,
i
+
max_slice
)
clips
.
append
(
subclip
)
i
+=
max_slice
n
=
5
result
=
[
clips
[
i
*
n
:(
i
+
1
)
*
n
]
for
i
in
range
((
len
(
clips
)
+
n
-
1
)
//
n
)]
print
(
len
(
result
))
for
j
in
range
(
len
(
result
)):
final1
.
append
(
mp
.
concatenate_videoclips
(
result
[
j
]))
final2
=
mp
.
concatenate_videoclips
(
final1
)
final2
.
write_videofile
(
self
.
fileName
+
'_highlights'
+
'.mp4'
)
import
pickle
import
csv
import
os
import
pandas
as
pd
import
re
import
math
import
google.oauth2.credentials
from
googleapiclient.discovery
import
build
from
googleapiclient.errors
import
HttpError
from
google_auth_oauthlib.flow
import
InstalledAppFlow
from
google.auth.transport.requests
import
Request
# parameter 지정
CLIENT_SECRETS_FILE
=
"/Users/ASUS/Desktop/work/3-1/디자인적사고/project/client_secret.json"
CLIENT_SECRETS_FILE
=
"/Users/user/Documents/카카오톡 받은 파일/api/client_secret.json"
SCOPES
=
[
'https://www.googleapis.com/auth/youtube.force-ssl'
]
API_SERVICE_NAME
=
'youtube'
API_VERSION
=
'v3'
# 인증 모듈
def
get_authenticated_service
():
credentials
=
None
if
os
.
path
.
exists
(
'token.pickle'
):
with
open
(
'token.pickle'
,
'rb'
)
as
token
:
credentials
=
pickle
.
load
(
token
)
# Check if the credentials are invalid or do not exist
if
not
credentials
or
not
credentials
.
valid
:
# Check if the credentials have expired
if
credentials
and
credentials
.
expired
and
credentials
.
refresh_token
:
credentials
.
refresh
(
Request
())
else
:
flow
=
InstalledAppFlow
.
from_client_secrets_file
(
CLIENT_SECRETS_FILE
,
SCOPES
)
credentials
=
flow
.
run_console
()
# Save the credentials for the next run
with
open
(
'token.pickle'
,
'wb'
)
as
token
:
pickle
.
dump
(
credentials
,
token
)
return
build
(
API_SERVICE_NAME
,
API_VERSION
,
credentials
=
credentials
)
# video comment 데이터프레임화
def
get_video_comments
(
service
,
**
kwargs
):
results
=
service
.
commentThreads
()
.
list
(
**
kwargs
)
.
execute
()
youtube_pd
=
pd
.
DataFrame
()
# filename = input('.csv 형태로 입력하세요')
while
results
:
for
item
in
results
[
'items'
]:
comment1
=
item
[
'snippet'
][
'topLevelComment'
][
'snippet'
][
'textDisplay'
]
# comment2 = item['snippet']['topLevelComment']['snippet']['publishedAt']
# comment3 = item['snippet']['topLevelComment']['snippet']['authorDisplayName']
# comment2 = item['snippet']['topLevelComment']['snippet']['viewerRating']
comment2
=
item
[
'snippet'
][
'topLevelComment'
][
'snippet'
][
'likeCount'
]
pd_data
=
{
"comment"
:
comment1
,
"likeCount"
:
comment2
}
youtube_pd
=
youtube_pd
.
append
(
pd_data
,
ignore_index
=
True
)
# youtube_pd.to_csv(filename, index=False, encoding='utf-8-sig')
# Check if another page exists
if
'nextPageToken'
in
results
:
kwargs
[
'pageToken'
]
=
results
[
'nextPageToken'
]
results
=
service
.
commentThreads
()
.
list
(
**
kwargs
)
.
execute
()
else
:
break
return
youtube_pd
# 코멘트에서 타임라인만 추출
def
make_video_timeline
(
commentFrame
,
duration
,
max_slice
):
youtube_pd_sorted_by_likeCount
=
commentFrame
.
sort_values
(
by
=
'likeCount'
)
# .str.split(" ") # .values.tolist()
#youtube_pd_sorted_by_likeCount = youtube_pd_sorted_by_likeCount.head(30) # 갯수 정해서 추출하기
comment
=
youtube_pd_sorted_by_likeCount
[
'comment'
]
comment_split
=
comment
.
str
.
split
(
" "
)
.
values
.
tolist
()
result
=
[]
for
i
in
range
(
len
(
comment_split
)):
for
j
in
range
(
len
(
comment_split
[
i
])):
if
":"
in
comment_split
[
i
][
j
]:
result
.
append
(
comment_split
[
i
][
j
])
hi
=
' '
.
join
(
result
)
timeline
=
re
.
findall
(
r'(\d{1,2}):(\d{2})'
,
hi
)
timelist
=
[]
for
groups
in
timeline
:
timelist
.
append
(
int
(
groups
[
0
])
*
60
+
int
(
groups
[
1
]))
timelist
.
sort
()
# print(timelist)
timecheck
=
[]
for
i
in
range
(
math
.
ceil
(
duration
/
max_slice
)):
timecheck
.
append
(
0
)
for
i
in
range
(
math
.
ceil
(
duration
/
max_slice
)):
for
j
in
timelist
:
if
i
<=
int
(
int
(
j
)
/
max_slice
)
<=
(
i
+
10
/
max_slice
):
timecheck
[
i
]
=
1
# print(timecheck)
return
timecheck
# 비디오 총 길이 추출
def
get_video_duration
(
service
,
**
kwargs
):
results
=
service
.
videos
()
.
list
(
**
kwargs
)
.
execute
()
comment_data
=
results
[
'items'
]
comment_data
=
comment_data
[
0
][
'contentDetails'
][
'duration'
]
match
=
re
.
match
(
r'PT(\d+H)?(\d+M)?(\d+S)?'
,
comment_data
)
.
groups
()
hours
=
_js_parseInt
(
match
[
0
])
if
match
[
0
]
else
0
minutes
=
_js_parseInt
(
match
[
1
])
if
match
[
1
]
else
0
seconds
=
_js_parseInt
(
match
[
2
])
if
match
[
2
]
else
0
return
hours
*
3600
+
minutes
*
60
+
seconds
# 문자열에서 숫자만 추출
def
_js_parseInt
(
string
):
return
int
(
''
.
join
([
x
for
x
in
string
if
x
.
isdigit
()]))
"""
if __name__ == '__main__':
# When running locally, disable OAuthlib's HTTPs verification. When
# running in production *do not* leave this option enabled.
os.environ['OAUTHLIB_INSECURE_TRANSPORT'] = '1'
service = get_authenticated_service()
video_id = input('Enter a video_id: ')
comments = get_video_comments(
service, part='snippet', videoId=video_id, textFormat='plainText')
video_duration = get_video_duration(
service, part='contentDetails', id=video_id)
# print(video_duration)
# print(comments)
commentdata = make_video_timeline(comments, video_duration)
print(commentdata)
"""
if
__name__
==
"__main__"
:
app
=
QApplication
(
sys
.
argv
)
myWindow
=
WindowClass
()
myWindow
.
show
()
sys
.
exit
(
app
.
exec_
())
Please
register
or
login
to post a comment